#ifndef LIBWALLY_CORE_WALLY_HPP
#define LIBWALLY_CORE_WALLY_HPP
#pragma once

#include <type_traits>
#include <string>
#include <wally_address.h>
#include <wally_anti_exfil.h>
#include <wally_bip32.h>
#include <wally_bip38.h>
#include <wally_bip39.h>
#include <wally_bip85.h>
#include <wally_core.h>
#include <wally_coinselection.h>
#include <wally_crypto.h>
#include <wally_descriptor.h>
#include <wally_map.h>
#include <wally_psbt.h>
#include <wally_script.h>
#include <wally_symmetric.h>
#include <wally_transaction.h>
#include <wally_elements.h>

/* These wrappers allow passing containers such as std::vector, std::array,
 * std::string and custom classes as input/output buffers to wally functions.
 */
namespace wally {

namespace detail {

// Caller must provide an implementation of this call for error checking.
// It may either throw an exception when ret != WALLY_OK or return the error code.
int check_ret(const char* func_name, int ret);

template <class P> inline auto get_p(const P& p, std::false_type, std::true_type) {
    return &p[0];
}
template <class P> inline auto get_p(const P& p, std::true_type, std::false_type) {
    return p;
}
template <class P> inline auto get_p(const P& p, std::false_type, std::false_type) {
    return p.get();
}
template <class P> inline auto get_p(const P& p) {
    return get_p(p, std::is_pointer<P>{}, std::is_array<P>{});
}
template <> inline auto get_p(const std::string& p) {
    return p.c_str();
}
template <> inline auto get_p(const std::nullptr_t& p) {
    return p;
}
} /* namespace detail */

/* BEGIN AUTOGENERATED */
inline int bip32_key_free(const struct ext_key* hdkey) {
    int ret = ::bip32_key_free(hdkey);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BASE58>
inline int bip32_key_from_base58(const BASE58& base58, struct ext_key* output) {
    int ret = ::bip32_key_from_base58(detail::get_p(base58), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BASE58>
inline int bip32_key_from_base58_alloc(const BASE58& base58, struct ext_key** output) {
    int ret = ::bip32_key_from_base58_alloc(detail::get_p(base58), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BASE58>
inline int bip32_key_from_base58_n(const BASE58& base58, size_t base58_len, struct ext_key* output) {
    int ret = ::bip32_key_from_base58_n(detail::get_p(base58), base58_len, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BASE58>
inline int bip32_key_from_base58_n_alloc(const BASE58& base58, size_t base58_len, struct ext_key** output) {
    int ret = ::bip32_key_from_base58_n_alloc(detail::get_p(base58), base58_len, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HDKEY>
inline int bip32_key_from_parent(const HDKEY& hdkey, uint32_t child_num, uint32_t flags, struct ext_key* output) {
    int ret = ::bip32_key_from_parent(detail::get_p(hdkey), child_num, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HDKEY>
inline int bip32_key_from_parent_alloc(const HDKEY& hdkey, uint32_t child_num, uint32_t flags, struct ext_key** output) {
    int ret = ::bip32_key_from_parent_alloc(detail::get_p(hdkey), child_num, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HDKEY, class CHILD_PATH>
inline int bip32_key_from_parent_path(const HDKEY& hdkey, const CHILD_PATH& child_path, uint32_t flags, struct ext_key* output) {
    int ret = ::bip32_key_from_parent_path(detail::get_p(hdkey), child_path.data(), child_path.size(), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HDKEY, class CHILD_PATH>
inline int bip32_key_from_parent_path_alloc(const HDKEY& hdkey, const CHILD_PATH& child_path, uint32_t flags, struct ext_key** output) {
    int ret = ::bip32_key_from_parent_path_alloc(detail::get_p(hdkey), child_path.data(), child_path.size(), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HDKEY, class PATH_STR>
inline int bip32_key_from_parent_path_str(const HDKEY& hdkey, const PATH_STR& path_str, uint32_t child_num, uint32_t flags, struct ext_key* output) {
    int ret = ::bip32_key_from_parent_path_str(detail::get_p(hdkey), detail::get_p(path_str), child_num, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HDKEY, class PATH_STR>
inline int bip32_key_from_parent_path_str_alloc(const HDKEY& hdkey, const PATH_STR& path_str, uint32_t child_num, uint32_t flags, struct ext_key** output) {
    int ret = ::bip32_key_from_parent_path_str_alloc(detail::get_p(hdkey), detail::get_p(path_str), child_num, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HDKEY, class PATH_STR>
inline int bip32_key_from_parent_path_str_n(const HDKEY& hdkey, const PATH_STR& path_str, size_t path_str_len, uint32_t child_num, uint32_t flags, struct ext_key* output) {
    int ret = ::bip32_key_from_parent_path_str_n(detail::get_p(hdkey), detail::get_p(path_str), path_str_len, child_num, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HDKEY, class PATH_STR>
inline int bip32_key_from_parent_path_str_n_alloc(const HDKEY& hdkey, const PATH_STR& path_str, size_t path_str_len, uint32_t child_num, uint32_t flags, struct ext_key** output) {
    int ret = ::bip32_key_from_parent_path_str_n_alloc(detail::get_p(hdkey), detail::get_p(path_str), path_str_len, child_num, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES>
inline int bip32_key_from_seed(const BYTES& bytes, uint32_t version, uint32_t flags, struct ext_key* output) {
    int ret = ::bip32_key_from_seed(bytes.data(), bytes.size(), version, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES>
inline int bip32_key_from_seed_alloc(const BYTES& bytes, uint32_t version, uint32_t flags, struct ext_key** output) {
    int ret = ::bip32_key_from_seed_alloc(bytes.data(), bytes.size(), version, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class HMAC_KEY>
inline int bip32_key_from_seed_custom(const BYTES& bytes, uint32_t version, const HMAC_KEY& hmac_key, uint32_t flags, struct ext_key* output) {
    int ret = ::bip32_key_from_seed_custom(bytes.data(), bytes.size(), version, hmac_key.data(), hmac_key.size(), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class HMAC_KEY>
inline int bip32_key_from_seed_custom_alloc(const BYTES& bytes, uint32_t version, const HMAC_KEY& hmac_key, uint32_t flags, struct ext_key** output) {
    int ret = ::bip32_key_from_seed_custom_alloc(bytes.data(), bytes.size(), version, hmac_key.data(), hmac_key.size(), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HDKEY, class BYTES_OUT>
inline int bip32_key_get_fingerprint(const HDKEY& hdkey, BYTES_OUT& bytes_out) {
    int ret = ::bip32_key_get_fingerprint(detail::get_p(hdkey), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class CHAIN_CODE, class PUB_KEY, class PRIV_KEY, class HASH160, class PARENT160>
inline int bip32_key_init(uint32_t version, uint32_t depth, uint32_t child_num, const CHAIN_CODE& chain_code, const PUB_KEY& pub_key, const PRIV_KEY& priv_key, const HASH160& hash160, const PARENT160& parent160, struct ext_key* output) {
    int ret = ::bip32_key_init(version, depth, child_num, chain_code.data(), chain_code.size(), pub_key.data(), pub_key.size(), priv_key.data(), priv_key.size(), hash160.data(), hash160.size(), parent160.data(), parent160.size(), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class CHAIN_CODE, class PUB_KEY, class PRIV_KEY, class HASH160, class PARENT160>
inline int bip32_key_init_alloc(uint32_t version, uint32_t depth, uint32_t child_num, const CHAIN_CODE& chain_code, const PUB_KEY& pub_key, const PRIV_KEY& priv_key, const HASH160& hash160, const PARENT160& parent160, struct ext_key** output) {
    int ret = ::bip32_key_init_alloc(version, depth, child_num, chain_code.data(), chain_code.size(), pub_key.data(), pub_key.size(), priv_key.data(), priv_key.size(), hash160.data(), hash160.size(), parent160.data(), parent160.size(), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HDKEY, class BYTES_OUT>
inline int bip32_key_serialize(const HDKEY& hdkey, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::bip32_key_serialize(detail::get_p(hdkey), flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

inline int bip32_key_strip_private_key(struct ext_key* hdkey) {
    int ret = ::bip32_key_strip_private_key(hdkey);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HDKEY>
inline int bip32_key_to_base58(const HDKEY& hdkey, uint32_t flags, char** output) {
    int ret = ::bip32_key_to_base58(detail::get_p(hdkey), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES>
inline int bip32_key_unserialize(const BYTES& bytes, struct ext_key* output) {
    int ret = ::bip32_key_unserialize(bytes.data(), bytes.size(), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES>
inline int bip32_key_unserialize_alloc(const BYTES& bytes, struct ext_key** output) {
    int ret = ::bip32_key_unserialize_alloc(bytes.data(), bytes.size(), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PATH_STR>
inline int bip32_path_from_str(const PATH_STR& path_str, uint32_t child_num, uint32_t multi_index, uint32_t flags, uint32_t* child_path_out, uint32_t child_path_out_len, size_t* written) {
    int ret = ::bip32_path_from_str(detail::get_p(path_str), child_num, multi_index, flags, child_path_out, child_path_out_len, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PATH_STR>
inline int bip32_path_from_str_n(const PATH_STR& path_str, size_t path_str_len, uint32_t child_num, uint32_t multi_index, uint32_t flags, uint32_t* child_path_out, uint32_t child_path_out_len, size_t* written) {
    int ret = ::bip32_path_from_str_n(detail::get_p(path_str), path_str_len, child_num, multi_index, flags, child_path_out, child_path_out_len, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PATH_STR>
inline int bip32_path_str_get_features(const PATH_STR& path_str, uint32_t* value_out) {
    int ret = ::bip32_path_str_get_features(detail::get_p(path_str), value_out);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PATH_STR>
inline int bip32_path_str_n_get_features(const PATH_STR& path_str, size_t path_str_len, uint32_t* value_out) {
    int ret = ::bip32_path_str_n_get_features(detail::get_p(path_str), path_str_len, value_out);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class PASS>
inline int bip38_from_private_key(const BYTES& bytes, const PASS& pass, uint32_t flags, char** output) {
    int ret = ::bip38_from_private_key(bytes.data(), bytes.size(), pass.data(), pass.size(), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BIP38>
inline int bip38_get_flags(const BIP38& bip38, size_t* written) {
    int ret = ::bip38_get_flags(detail::get_p(bip38), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class PASS, class BYTES_OUT>
inline int bip38_raw_from_private_key(const BYTES& bytes, const PASS& pass, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::bip38_raw_from_private_key(bytes.data(), bytes.size(), pass.data(), pass.size(), flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES>
inline int bip38_raw_get_flags(const BYTES& bytes, size_t* written) {
    int ret = ::bip38_raw_get_flags(bytes.data(), bytes.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class PASS, class BYTES_OUT>
inline int bip38_raw_to_private_key(const BYTES& bytes, const PASS& pass, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::bip38_raw_to_private_key(bytes.data(), bytes.size(), pass.data(), pass.size(), flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BIP38, class PASS, class BYTES_OUT>
inline int bip38_to_private_key(const BIP38& bip38, const PASS& pass, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::bip38_to_private_key(detail::get_p(bip38), pass.data(), pass.size(), flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

inline int bip39_get_languages(char** output) {
    int ret = ::bip39_get_languages(output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class W>
inline int bip39_get_word(const W& w, size_t index, char** output) {
    int ret = ::bip39_get_word(detail::get_p(w), index, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class LANG>
inline int bip39_get_wordlist(const LANG& lang, struct words** output) {
    int ret = ::bip39_get_wordlist(detail::get_p(lang), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class W, class BYTES>
inline int bip39_mnemonic_from_bytes(const W& w, const BYTES& bytes, char** output) {
    int ret = ::bip39_mnemonic_from_bytes(detail::get_p(w), bytes.data(), bytes.size(), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class W, class MNEMONIC, class BYTES_OUT>
inline int bip39_mnemonic_to_bytes(const W& w, const MNEMONIC& mnemonic, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::bip39_mnemonic_to_bytes(detail::get_p(w), detail::get_p(mnemonic), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MNEMONIC, class PASSPHRASE, class BYTES_OUT>
inline int bip39_mnemonic_to_seed(const MNEMONIC& mnemonic, const PASSPHRASE& passphrase, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::bip39_mnemonic_to_seed(detail::get_p(mnemonic), detail::get_p(passphrase), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MNEMONIC, class PASSPHRASE, class BYTES_OUT>
inline int bip39_mnemonic_to_seed512(const MNEMONIC& mnemonic, const PASSPHRASE& passphrase, BYTES_OUT& bytes_out) {
    int ret = ::bip39_mnemonic_to_seed512(detail::get_p(mnemonic), detail::get_p(passphrase), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class W>
inline int bip39_mnemonic_validate(const W& w, const char* mnemonic) {
    int ret = ::bip39_mnemonic_validate(detail::get_p(w), mnemonic);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HDKEY, class LANG, class BYTES_OUT>
inline int bip85_get_bip39_entropy(const HDKEY& hdkey, const LANG& lang, uint32_t num_words, uint32_t index, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::bip85_get_bip39_entropy(detail::get_p(hdkey), detail::get_p(lang), num_words, index, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int bip85_get_languages(char** output) {
    int ret = ::bip85_get_languages(output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HDKEY, class BYTES_OUT>
inline int bip85_get_rsa_entropy(const HDKEY& hdkey, uint32_t key_bits, uint32_t index, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::bip85_get_rsa_entropy(detail::get_p(hdkey), key_bits, index, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class ADDR_FAMILY>
inline int addr_segwit_from_bytes(const BYTES& bytes, const ADDR_FAMILY& addr_family, uint32_t flags, char** output) {
    int ret = ::wally_addr_segwit_from_bytes(bytes.data(), bytes.size(), detail::get_p(addr_family), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ADDR, class ADDR_FAMILY>
inline int addr_segwit_get_version(const ADDR& addr, const ADDR_FAMILY& addr_family, uint32_t flags, size_t* written) {
    int ret = ::wally_addr_segwit_get_version(detail::get_p(addr), detail::get_p(addr_family), flags, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ADDR, class ADDR_FAMILY>
inline int addr_segwit_n_get_version(const ADDR& addr, size_t addr_len, const ADDR_FAMILY& addr_family, size_t addr_family_len, uint32_t flags, size_t* written) {
    int ret = ::wally_addr_segwit_n_get_version(detail::get_p(addr), addr_len, detail::get_p(addr_family), addr_family_len, flags, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ADDR, class ADDR_FAMILY, class BYTES_OUT>
inline int addr_segwit_n_to_bytes(const ADDR& addr, size_t addr_len, const ADDR_FAMILY& addr_family, size_t addr_family_len, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_addr_segwit_n_to_bytes(detail::get_p(addr), addr_len, detail::get_p(addr_family), addr_family_len, flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ADDR, class ADDR_FAMILY, class BYTES_OUT>
inline int addr_segwit_to_bytes(const ADDR& addr, const ADDR_FAMILY& addr_family, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_addr_segwit_to_bytes(detail::get_p(addr), detail::get_p(addr_family), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ADDR, class BYTES_OUT>
inline int address_to_scriptpubkey(const ADDR& addr, uint32_t network, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_address_to_scriptpubkey(detail::get_p(addr), network, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ENTROPY, class BYTES_OUT>
inline int ae_host_commit_from_bytes(const ENTROPY& entropy, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_ae_host_commit_from_bytes(entropy.data(), entropy.size(), flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PRIV_KEY, class BYTES, class ENTROPY, class BYTES_OUT>
inline int ae_sig_from_bytes(const PRIV_KEY& priv_key, const BYTES& bytes, const ENTROPY& entropy, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_ae_sig_from_bytes(priv_key.data(), priv_key.size(), bytes.data(), bytes.size(), entropy.data(), entropy.size(), flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PRIV_KEY, class BYTES, class COMMITMENT, class S2C_OPENING_OUT>
inline int ae_signer_commit_from_bytes(const PRIV_KEY& priv_key, const BYTES& bytes, const COMMITMENT& commitment, uint32_t flags, S2C_OPENING_OUT& s2c_opening_out) {
    int ret = ::wally_ae_signer_commit_from_bytes(priv_key.data(), priv_key.size(), bytes.data(), bytes.size(), commitment.data(), commitment.size(), flags, s2c_opening_out.data(), s2c_opening_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PUB_KEY, class BYTES, class ENTROPY, class S2C_OPENING, class SIG>
inline bool ae_verify(const PUB_KEY& pub_key, const BYTES& bytes, const ENTROPY& entropy, const S2C_OPENING& s2c_opening, uint32_t flags, const SIG& sig) {
    int ret = ::wally_ae_verify(pub_key.data(), pub_key.size(), bytes.data(), bytes.size(), entropy.data(), entropy.size(), s2c_opening.data(), s2c_opening.size(), flags, sig.data(), sig.size());
    return ret == WALLY_OK;
}

template <class KEY, class BYTES, class BYTES_OUT>
inline int aes(const KEY& key, const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_aes(key.data(), key.size(), bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class KEY, class IV, class BYTES, class BYTES_OUT>
inline int aes_cbc(const KEY& key, const IV& iv, const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_aes_cbc(key.data(), key.size(), iv.data(), iv.size(), bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class KEY, class IV, class BYTES>
inline int aes_cbc_get_maximum_length(const KEY& key, const IV& iv, const BYTES& bytes, uint32_t flags, size_t* written) {
    int ret = ::wally_aes_cbc_get_maximum_length(key.data(), key.size(), iv.data(), iv.size(), bytes.data(), bytes.size(), flags, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PRIV_KEY, class IV, class BYTES, class PUB_KEY, class LABEL, class BYTES_OUT>
inline int aes_cbc_with_ecdh_key(const PRIV_KEY& priv_key, const IV& iv, const BYTES& bytes, const PUB_KEY& pub_key, const LABEL& label, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_aes_cbc_with_ecdh_key(priv_key.data(), priv_key.size(), iv.data(), iv.size(), bytes.data(), bytes.size(), pub_key.data(), pub_key.size(), label.data(), label.size(), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PRIV_KEY, class IV, class BYTES, class PUB_KEY, class LABEL>
inline int aes_cbc_with_ecdh_key_get_maximum_length(const PRIV_KEY& priv_key, const IV& iv, const BYTES& bytes, const PUB_KEY& pub_key, const LABEL& label, uint32_t flags, size_t* written) {
    int ret = ::wally_aes_cbc_with_ecdh_key_get_maximum_length(priv_key.data(), priv_key.size(), iv.data(), iv.size(), bytes.data(), bytes.size(), pub_key.data(), pub_key.size(), label.data(), label.size(), flags, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class KEY, class BYTES>
inline int aes_len(const KEY& key, const BYTES& bytes, uint32_t flags, size_t* written) {
    int ret = ::wally_aes_len(key.data(), key.size(), bytes.data(), bytes.size(), flags, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES>
inline int base58_from_bytes(const BYTES& bytes, uint32_t flags, char** output) {
    int ret = ::wally_base58_from_bytes(bytes.data(), bytes.size(), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STR_IN>
inline int base58_get_length(const STR_IN& str_in, size_t* written) {
    int ret = ::wally_base58_get_length(detail::get_p(str_in), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STR_IN>
inline int base58_n_get_length(const STR_IN& str_in, size_t str_len, size_t* written) {
    int ret = ::wally_base58_n_get_length(detail::get_p(str_in), str_len, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STR_IN, class BYTES_OUT>
inline int base58_n_to_bytes(const STR_IN& str_in, size_t str_len, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_base58_n_to_bytes(detail::get_p(str_in), str_len, flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STR_IN, class BYTES_OUT>
inline int base58_to_bytes(const STR_IN& str_in, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_base58_to_bytes(detail::get_p(str_in), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES>
inline int base64_from_bytes(const BYTES& bytes, uint32_t flags, char** output) {
    int ret = ::wally_base64_from_bytes(bytes.data(), bytes.size(), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STR_IN>
inline int base64_get_maximum_length(const STR_IN& str_in, uint32_t flags, size_t* written) {
    int ret = ::wally_base64_get_maximum_length(detail::get_p(str_in), flags, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STR_IN>
inline int base64_n_get_maximum_length(const STR_IN& str_in, size_t str_len, uint32_t flags, size_t* written) {
    int ret = ::wally_base64_n_get_maximum_length(detail::get_p(str_in), str_len, flags, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STR_IN, class BYTES_OUT>
inline int base64_n_to_bytes(const STR_IN& str_in, size_t str_len, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_base64_n_to_bytes(detail::get_p(str_in), str_len, flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STR_IN, class BYTES_OUT>
inline int base64_to_bytes(const STR_IN& str_in, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_base64_to_bytes(detail::get_p(str_in), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HDKEY, class ADDR_FAMILY>
inline int bip32_key_to_addr_segwit(const HDKEY& hdkey, const ADDR_FAMILY& addr_family, uint32_t flags, char** output) {
    int ret = ::wally_bip32_key_to_addr_segwit(detail::get_p(hdkey), detail::get_p(addr_family), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HDKEY>
inline int bip32_key_to_address(const HDKEY& hdkey, uint32_t flags, uint32_t version, char** output) {
    int ret = ::wally_bip32_key_to_address(detail::get_p(hdkey), flags, version, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class TAG, class BYTES_OUT>
inline int bip340_tagged_hash(const BYTES& bytes, const TAG& tag, BYTES_OUT& bytes_out) {
    int ret = ::wally_bip340_tagged_hash(bytes.data(), bytes.size(), detail::get_p(tag), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES>
inline int bzero(const BYTES& bytes, size_t bytes_len) {
    int ret = ::wally_bzero(detail::get_p(bytes), bytes_len);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int cleanup(uint32_t flags) {
    int ret = ::wally_cleanup(flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_canonicalize(const DESCRIPTOR& descriptor, uint32_t flags, char** output) {
    int ret = ::wally_descriptor_canonicalize(detail::get_p(descriptor), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int descriptor_free(struct wally_descriptor* descriptor) {
    int ret = ::wally_descriptor_free(descriptor);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_get_checksum(const DESCRIPTOR& descriptor, uint32_t flags, char** output) {
    int ret = ::wally_descriptor_get_checksum(detail::get_p(descriptor), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_get_depth(const DESCRIPTOR& descriptor, uint32_t* value_out) {
    int ret = ::wally_descriptor_get_depth(detail::get_p(descriptor), value_out);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_get_features(const DESCRIPTOR& descriptor, uint32_t* value_out) {
    int ret = ::wally_descriptor_get_features(detail::get_p(descriptor), value_out);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_get_key(const DESCRIPTOR& descriptor, size_t index, char** output) {
    int ret = ::wally_descriptor_get_key(detail::get_p(descriptor), index, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_get_key_child_path_str(const DESCRIPTOR& descriptor, size_t index, char** output) {
    int ret = ::wally_descriptor_get_key_child_path_str(detail::get_p(descriptor), index, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_get_key_child_path_str_len(const DESCRIPTOR& descriptor, size_t index, size_t* written) {
    int ret = ::wally_descriptor_get_key_child_path_str_len(detail::get_p(descriptor), index, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_get_key_features(const DESCRIPTOR& descriptor, size_t index, uint32_t* value_out) {
    int ret = ::wally_descriptor_get_key_features(detail::get_p(descriptor), index, value_out);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR, class BYTES_OUT>
inline int descriptor_get_key_origin_fingerprint(const DESCRIPTOR& descriptor, size_t index, BYTES_OUT& bytes_out) {
    int ret = ::wally_descriptor_get_key_origin_fingerprint(detail::get_p(descriptor), index, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_get_key_origin_path_str(const DESCRIPTOR& descriptor, size_t index, char** output) {
    int ret = ::wally_descriptor_get_key_origin_path_str(detail::get_p(descriptor), index, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_get_key_origin_path_str_len(const DESCRIPTOR& descriptor, size_t index, size_t* written) {
    int ret = ::wally_descriptor_get_key_origin_path_str_len(detail::get_p(descriptor), index, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_get_network(const DESCRIPTOR& descriptor, uint32_t* value_out) {
    int ret = ::wally_descriptor_get_network(detail::get_p(descriptor), value_out);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_get_num_keys(const DESCRIPTOR& descriptor, uint32_t* value_out) {
    int ret = ::wally_descriptor_get_num_keys(detail::get_p(descriptor), value_out);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_get_num_paths(const DESCRIPTOR& descriptor, uint32_t* value_out) {
    int ret = ::wally_descriptor_get_num_paths(detail::get_p(descriptor), value_out);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_get_num_variants(const DESCRIPTOR& descriptor, uint32_t* value_out) {
    int ret = ::wally_descriptor_get_num_variants(detail::get_p(descriptor), value_out);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR, class VARS_IN>
inline int descriptor_parse(const DESCRIPTOR& descriptor, const VARS_IN& vars_in, uint32_t network, uint32_t flags, struct wally_descriptor** output) {
    int ret = ::wally_descriptor_parse(detail::get_p(descriptor), detail::get_p(vars_in), network, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_set_network(const DESCRIPTOR& descriptor, uint32_t network) {
    int ret = ::wally_descriptor_set_network(detail::get_p(descriptor), network);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_to_address(const DESCRIPTOR& descriptor, uint32_t variant, uint32_t multi_index, uint32_t child_num, uint32_t flags, char** output) {
    int ret = ::wally_descriptor_to_address(detail::get_p(descriptor), variant, multi_index, child_num, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_to_addresses(const DESCRIPTOR& descriptor, uint32_t variant, uint32_t multi_index, uint32_t child_num, uint32_t flags, char** output, size_t num_outputs) {
    int ret = ::wally_descriptor_to_addresses(detail::get_p(descriptor), variant, multi_index, child_num, flags, output, num_outputs);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR, class BYTES_OUT>
inline int descriptor_to_script(const DESCRIPTOR& descriptor, uint32_t depth, uint32_t index, uint32_t variant, uint32_t multi_index, uint32_t child_num, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_descriptor_to_script(detail::get_p(descriptor), depth, index, variant, multi_index, child_num, flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class DESCRIPTOR>
inline int descriptor_to_script_get_maximum_length(const DESCRIPTOR& descriptor, uint32_t depth, uint32_t index, uint32_t variant, uint32_t multi_index, uint32_t child_num, uint32_t flags, size_t* written) {
    int ret = ::wally_descriptor_to_script_get_maximum_length(detail::get_p(descriptor), depth, index, variant, multi_index, child_num, flags, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PRIV_KEY, class MERKLE_ROOT, class BYTES_OUT>
inline int ec_private_key_bip341_tweak(const PRIV_KEY& priv_key, const MERKLE_ROOT& merkle_root, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_private_key_bip341_tweak(priv_key.data(), priv_key.size(), merkle_root.data(), merkle_root.size(), flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PRIV_KEY>
inline bool ec_private_key_verify(const PRIV_KEY& priv_key) {
    int ret = ::wally_ec_private_key_verify(priv_key.data(), priv_key.size());
    return ret == WALLY_OK;
}

template <class PUB_KEY, class MERKLE_ROOT, class BYTES_OUT>
inline int ec_public_key_bip341_tweak(const PUB_KEY& pub_key, const MERKLE_ROOT& merkle_root, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_public_key_bip341_tweak(pub_key.data(), pub_key.size(), merkle_root.data(), merkle_root.size(), flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PUB_KEY, class BYTES_OUT>
inline int ec_public_key_decompress(const PUB_KEY& pub_key, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_public_key_decompress(pub_key.data(), pub_key.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PRIV_KEY, class BYTES_OUT>
inline int ec_public_key_from_private_key(const PRIV_KEY& priv_key, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_public_key_from_private_key(priv_key.data(), priv_key.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PUB_KEY, class BYTES_OUT>
inline int ec_public_key_negate(const PUB_KEY& pub_key, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_public_key_negate(pub_key.data(), pub_key.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PUB_KEY>
inline bool ec_public_key_verify(const PUB_KEY& pub_key) {
    int ret = ::wally_ec_public_key_verify(pub_key.data(), pub_key.size());
    return ret == WALLY_OK;
}

template <class SCALAR, class OPERAND, class BYTES_OUT>
inline int ec_scalar_add(const SCALAR& scalar, const OPERAND& operand, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_scalar_add(scalar.data(), scalar.size(), operand.data(), operand.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SCALAR, class OPERAND>
inline int ec_scalar_add_to(SCALAR& scalar, const OPERAND& operand) {
    int ret = ::wally_ec_scalar_add_to(scalar.data(), scalar.size(), operand.data(), operand.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SCALAR, class OPERAND, class BYTES_OUT>
inline int ec_scalar_multiply(const SCALAR& scalar, const OPERAND& operand, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_scalar_multiply(scalar.data(), scalar.size(), operand.data(), operand.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SCALAR, class OPERAND>
inline int ec_scalar_multiply_by(SCALAR& scalar, const OPERAND& operand) {
    int ret = ::wally_ec_scalar_multiply_by(scalar.data(), scalar.size(), operand.data(), operand.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SCALAR, class OPERAND, class BYTES_OUT>
inline int ec_scalar_subtract(const SCALAR& scalar, const OPERAND& operand, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_scalar_subtract(scalar.data(), scalar.size(), operand.data(), operand.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SCALAR, class OPERAND>
inline int ec_scalar_subtract_from(SCALAR& scalar, const OPERAND& operand) {
    int ret = ::wally_ec_scalar_subtract_from(scalar.data(), scalar.size(), operand.data(), operand.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SCALAR>
inline bool ec_scalar_verify(const SCALAR& scalar) {
    int ret = ::wally_ec_scalar_verify(scalar.data(), scalar.size());
    return ret == WALLY_OK;
}

template <class PRIV_KEY, class BYTES, class BYTES_OUT>
inline int ec_sig_from_bytes(const PRIV_KEY& priv_key, const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_sig_from_bytes(priv_key.data(), priv_key.size(), bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PRIV_KEY, class BYTES, class AUX_RAND, class BYTES_OUT>
inline int ec_sig_from_bytes_aux(const PRIV_KEY& priv_key, const BYTES& bytes, const AUX_RAND& aux_rand, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_sig_from_bytes_aux(priv_key.data(), priv_key.size(), bytes.data(), bytes.size(), aux_rand.data(), aux_rand.size(), flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PRIV_KEY, class BYTES, class AUX_RAND>
inline int ec_sig_from_bytes_aux_len(const PRIV_KEY& priv_key, const BYTES& bytes, const AUX_RAND& aux_rand, uint32_t flags, size_t* written) {
    int ret = ::wally_ec_sig_from_bytes_aux_len(priv_key.data(), priv_key.size(), bytes.data(), bytes.size(), aux_rand.data(), aux_rand.size(), flags, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PRIV_KEY, class BYTES>
inline int ec_sig_from_bytes_len(const PRIV_KEY& priv_key, const BYTES& bytes, uint32_t flags, size_t* written) {
    int ret = ::wally_ec_sig_from_bytes_len(priv_key.data(), priv_key.size(), bytes.data(), bytes.size(), flags, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int ec_sig_from_der(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_sig_from_der(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SIG, class BYTES_OUT>
inline int ec_sig_normalize(const SIG& sig, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_sig_normalize(sig.data(), sig.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SIG, class BYTES_OUT>
inline int ec_sig_to_der(const SIG& sig, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_ec_sig_to_der(sig.data(), sig.size(), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class SIG, class BYTES_OUT>
inline int ec_sig_to_public_key(const BYTES& bytes, const SIG& sig, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_sig_to_public_key(bytes.data(), bytes.size(), sig.data(), sig.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PUB_KEY, class BYTES, class SIG>
inline bool ec_sig_verify(const PUB_KEY& pub_key, const BYTES& bytes, uint32_t flags, const SIG& sig) {
    int ret = ::wally_ec_sig_verify(pub_key.data(), pub_key.size(), bytes.data(), bytes.size(), flags, sig.data(), sig.size());
    return ret == WALLY_OK;
}

template <class PUB_KEY>
inline bool ec_xonly_public_key_verify(const PUB_KEY& pub_key) {
    int ret = ::wally_ec_xonly_public_key_verify(pub_key.data(), pub_key.size());
    return ret == WALLY_OK;
}

template <class PUB_KEY, class PRIV_KEY, class BYTES_OUT>
inline int ecdh(const PUB_KEY& pub_key, const PRIV_KEY& priv_key, BYTES_OUT& bytes_out) {
    int ret = ::wally_ecdh(pub_key.data(), pub_key.size(), priv_key.data(), priv_key.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int format_bitcoin_message(const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_format_bitcoin_message(bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int free_string(char* str) {
    int ret = ::wally_free_string(str);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int get_build_version(uint32_t* value) {
    int ret = ::wally_get_build_version(value);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TXHASHES, class UTXO_INDICES, class BYTES_OUT>
inline int get_hash_prevouts(const TXHASHES& txhashes, const UTXO_INDICES& utxo_indices, BYTES_OUT& bytes_out) {
    int ret = ::wally_get_hash_prevouts(txhashes.data(), txhashes.size(), utxo_indices.data(), utxo_indices.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

inline int get_operations(struct wally_operations* output) {
    int ret = ::wally_get_operations(output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int hash160(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_hash160(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES>
inline int hex_from_bytes(const BYTES& bytes, char** output) {
    int ret = ::wally_hex_from_bytes(bytes.data(), bytes.size(), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HEX, class BYTES_OUT>
inline int hex_n_to_bytes(const HEX& hex, size_t hex_len, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_hex_n_to_bytes(detail::get_p(hex), hex_len, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HEX>
inline bool hex_n_verify(const HEX& hex, size_t hex_len) {
    int ret = ::wally_hex_n_verify(detail::get_p(hex), hex_len);
    return ret == WALLY_OK;
}

template <class HEX, class BYTES_OUT>
inline int hex_to_bytes(const HEX& hex, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_hex_to_bytes(detail::get_p(hex), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline bool hex_verify(const char* hex) {
    int ret = ::wally_hex_verify(hex);
    return ret == WALLY_OK;
}

template <class KEY, class BYTES, class BYTES_OUT>
inline int hmac_sha256(const KEY& key, const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_hmac_sha256(key.data(), key.size(), bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class KEY, class BYTES, class BYTES_OUT>
inline int hmac_sha512(const KEY& key, const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_hmac_sha512(key.data(), key.size(), bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

inline int init(uint32_t flags) {
    int ret = ::wally_init(flags);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int is_elements_build(size_t* written) {
    int ret = ::wally_is_elements_build(written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class KEY, class VAL>
inline bool keypath_bip32_verify(const KEY& key, const VAL& val) {
    int ret = ::wally_keypath_bip32_verify(key.data(), key.size(), val.data(), val.size());
    return ret == WALLY_OK;
}

template <class VAL, class BYTES_OUT>
inline int keypath_get_fingerprint(const VAL& val, BYTES_OUT& bytes_out) {
    int ret = ::wally_keypath_get_fingerprint(val.data(), val.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class VAL>
inline int keypath_get_path(const VAL& val, uint32_t* child_path_out, size_t child_path_out_len, size_t* written) {
    int ret = ::wally_keypath_get_path(val.data(), val.size(), child_path_out, child_path_out_len, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class VAL>
inline int keypath_get_path_len(const VAL& val, size_t* written) {
    int ret = ::wally_keypath_get_path_len(val.data(), val.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class KEY, class VAL>
inline bool keypath_public_key_verify(const KEY& key, const VAL& val) {
    int ret = ::wally_keypath_public_key_verify(key.data(), key.size(), val.data(), val.size());
    return ret == WALLY_OK;
}

template <class KEY, class VAL>
inline bool keypath_xonly_public_key_verify(const KEY& key, const VAL& val) {
    int ret = ::wally_keypath_xonly_public_key_verify(key.data(), key.size(), val.data(), val.size());
    return ret == WALLY_OK;
}

template <class MAP_IN, class KEY, class VALUE>
inline int map_add(const MAP_IN& map_in, const KEY& key, const VALUE& value) {
    int ret = ::wally_map_add(detail::get_p(map_in), key.data(), key.size(), value.data(), value.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class VALUE>
inline int map_add_integer(const MAP_IN& map_in, uint32_t key, const VALUE& value) {
    int ret = ::wally_map_add_integer(detail::get_p(map_in), key, value.data(), value.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN>
inline int map_assign(const MAP_IN& map_in, const struct wally_map* source) {
    int ret = ::wally_map_assign(detail::get_p(map_in), source);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int map_clear(struct wally_map* map_in) {
    int ret = ::wally_map_clear(map_in);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN>
inline int map_combine(const MAP_IN& map_in, const struct wally_map* source) {
    int ret = ::wally_map_combine(detail::get_p(map_in), source);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class KEY>
inline int map_find(const MAP_IN& map_in, const KEY& key, size_t* written) {
    int ret = ::wally_map_find(detail::get_p(map_in), key.data(), key.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class HDKEY>
inline int map_find_bip32_public_key_from(const MAP_IN& map_in, size_t index, const HDKEY& hdkey, size_t* written) {
    int ret = ::wally_map_find_bip32_public_key_from(detail::get_p(map_in), index, detail::get_p(hdkey), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class KEY>
inline int map_find_from(const MAP_IN& map_in, size_t index, const KEY& key, size_t* written) {
    int ret = ::wally_map_find_from(detail::get_p(map_in), index, key.data(), key.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN>
inline int map_find_integer(const MAP_IN& map_in, uint32_t key, size_t* written) {
    int ret = ::wally_map_find_integer(detail::get_p(map_in), key, written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int map_free(struct wally_map* map_in) {
    int ret = ::wally_map_free(map_in);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class BYTES_OUT>
inline int map_get_item(const MAP_IN& map_in, size_t index, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_map_get_item(detail::get_p(map_in), index, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN>
inline int map_get_item_integer_key(const MAP_IN& map_in, size_t index, size_t* written) {
    int ret = ::wally_map_get_item_integer_key(detail::get_p(map_in), index, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class BYTES_OUT>
inline int map_get_item_key(const MAP_IN& map_in, size_t index, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_map_get_item_key(detail::get_p(map_in), index, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN>
inline int map_get_item_key_length(const MAP_IN& map_in, size_t index, size_t* written) {
    int ret = ::wally_map_get_item_key_length(detail::get_p(map_in), index, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN>
inline int map_get_item_length(const MAP_IN& map_in, size_t index, size_t* written) {
    int ret = ::wally_map_get_item_length(detail::get_p(map_in), index, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN>
inline int map_get_num_items(const MAP_IN& map_in, size_t* written) {
    int ret = ::wally_map_get_num_items(detail::get_p(map_in), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class KEY, class VAL>
inline bool map_hash_preimage_verify(const KEY& key, const VAL& val) {
    int ret = ::wally_map_hash_preimage_verify(key.data(), key.size(), val.data(), val.size());
    return ret == WALLY_OK;
}

inline int map_init(size_t allocation_len, wally_map_verify_fn_t verify_fn, struct wally_map* output) {
    int ret = ::wally_map_init(allocation_len, verify_fn, output);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int map_init_alloc(size_t allocation_len, wally_map_verify_fn_t verify_fn, struct wally_map** output) {
    int ret = ::wally_map_init_alloc(allocation_len, verify_fn, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class PUB_KEY, class FINGERPRINT, class CHILD_PATH>
inline int map_keypath_add(const MAP_IN& map_in, const PUB_KEY& pub_key, const FINGERPRINT& fingerprint, const CHILD_PATH& child_path) {
    int ret = ::wally_map_keypath_add(detail::get_p(map_in), pub_key.data(), pub_key.size(), fingerprint.data(), fingerprint.size(), child_path.data(), child_path.size());
    return detail::check_ret(__FUNCTION__, ret);
}

inline int map_keypath_bip32_init_alloc(size_t allocation_len, struct wally_map** output) {
    int ret = ::wally_map_keypath_bip32_init_alloc(allocation_len, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class HDKEY>
inline int map_keypath_get_bip32_key_from_alloc(const MAP_IN& map_in, size_t index, const HDKEY& hdkey, struct ext_key** output) {
    int ret = ::wally_map_keypath_get_bip32_key_from_alloc(detail::get_p(map_in), index, detail::get_p(hdkey), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class BYTES_OUT>
inline int map_keypath_get_item_fingerprint(const MAP_IN& map_in, size_t index, BYTES_OUT& bytes_out) {
    int ret = ::wally_map_keypath_get_item_fingerprint(detail::get_p(map_in), index, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN>
inline int map_keypath_get_item_path(const MAP_IN& map_in, size_t index, uint32_t* child_path_out, size_t child_path_out_len, size_t* written) {
    int ret = ::wally_map_keypath_get_item_path(detail::get_p(map_in), index, child_path_out, child_path_out_len, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN>
inline int map_keypath_get_item_path_len(const MAP_IN& map_in, size_t index, size_t* written) {
    int ret = ::wally_map_keypath_get_item_path_len(detail::get_p(map_in), index, written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int map_keypath_public_key_init_alloc(size_t allocation_len, struct wally_map** output) {
    int ret = ::wally_map_keypath_public_key_init_alloc(allocation_len, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class PUB_KEY, class MERKLE_HASHES>
inline int map_merkle_path_add(const MAP_IN& map_in, const PUB_KEY& pub_key, const MERKLE_HASHES& merkle_hashes) {
    int ret = ::wally_map_merkle_path_add(detail::get_p(map_in), pub_key.data(), pub_key.size(), merkle_hashes.data(), merkle_hashes.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class VALUE>
inline int map_preimage_hash160_add(const MAP_IN& map_in, const VALUE& value) {
    int ret = ::wally_map_preimage_hash160_add(detail::get_p(map_in), value.data(), value.size());
    return detail::check_ret(__FUNCTION__, ret);
}

inline int map_preimage_init_alloc(size_t allocation_len, struct wally_map** output) {
    int ret = ::wally_map_preimage_init_alloc(allocation_len, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class VALUE>
inline int map_preimage_ripemd160_add(const MAP_IN& map_in, const VALUE& value) {
    int ret = ::wally_map_preimage_ripemd160_add(detail::get_p(map_in), value.data(), value.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class VALUE>
inline int map_preimage_sha256_add(const MAP_IN& map_in, const VALUE& value) {
    int ret = ::wally_map_preimage_sha256_add(detail::get_p(map_in), value.data(), value.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class VALUE>
inline int map_preimage_sha256d_add(const MAP_IN& map_in, const VALUE& value) {
    int ret = ::wally_map_preimage_sha256d_add(detail::get_p(map_in), value.data(), value.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class KEY>
inline int map_remove(const MAP_IN& map_in, const KEY& key) {
    int ret = ::wally_map_remove(detail::get_p(map_in), key.data(), key.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN>
inline int map_remove_integer(const MAP_IN& map_in, uint32_t key) {
    int ret = ::wally_map_remove_integer(detail::get_p(map_in), key);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class KEY, class VALUE>
inline int map_replace(const MAP_IN& map_in, const KEY& key, const VALUE& value) {
    int ret = ::wally_map_replace(detail::get_p(map_in), key.data(), key.size(), value.data(), value.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN, class VALUE>
inline int map_replace_integer(const MAP_IN& map_in, uint32_t key, const VALUE& value) {
    int ret = ::wally_map_replace_integer(detail::get_p(map_in), key, value.data(), value.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class MAP_IN>
inline int map_sort(const MAP_IN& map_in, uint32_t flags) {
    int ret = ::wally_map_sort(detail::get_p(map_in), flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class KEY, class VAL>
inline bool merkle_path_xonly_public_key_verify(const KEY& key, const VAL& val) {
    int ret = ::wally_merkle_path_xonly_public_key_verify(key.data(), key.size(), val.data(), val.size());
    return ret == WALLY_OK;
}

template <class PASS, class SALT, class BYTES_OUT>
inline int pbkdf2_hmac_sha256(const PASS& pass, const SALT& salt, uint32_t flags, uint32_t cost, BYTES_OUT& bytes_out) {
    int ret = ::wally_pbkdf2_hmac_sha256(pass.data(), pass.size(), salt.data(), salt.size(), flags, cost, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PASS, class SALT, class BYTES_OUT>
inline int pbkdf2_hmac_sha512(const PASS& pass, const SALT& salt, uint32_t flags, uint32_t cost, BYTES_OUT& bytes_out) {
    int ret = ::wally_pbkdf2_hmac_sha512(pass.data(), pass.size(), salt.data(), salt.size(), flags, cost, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT, class PUB_KEY, class TAPLEAF_HASHES, class FINGERPRINT, class CHILD_PATH>
inline int psbt_add_input_taproot_keypath(const PSBT& psbt, uint32_t index, uint32_t flags, const PUB_KEY& pub_key, const TAPLEAF_HASHES& tapleaf_hashes, const FINGERPRINT& fingerprint, const CHILD_PATH& child_path) {
    int ret = ::wally_psbt_add_input_taproot_keypath(detail::get_p(psbt), index, flags, pub_key.data(), pub_key.size(), tapleaf_hashes.data(), tapleaf_hashes.size(), fingerprint.data(), fingerprint.size(), child_path.data(), child_path.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT, class PUB_KEY, class TAPLEAF_HASHES, class FINGERPRINT, class CHILD_PATH>
inline int psbt_add_output_taproot_keypath(const PSBT& psbt, uint32_t index, uint32_t flags, const PUB_KEY& pub_key, const TAPLEAF_HASHES& tapleaf_hashes, const FINGERPRINT& fingerprint, const CHILD_PATH& child_path) {
    int ret = ::wally_psbt_add_output_taproot_keypath(detail::get_p(psbt), index, flags, pub_key.data(), pub_key.size(), tapleaf_hashes.data(), tapleaf_hashes.size(), fingerprint.data(), fingerprint.size(), child_path.data(), child_path.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_add_tx_input_at(const PSBT& psbt, uint32_t index, uint32_t flags, const struct wally_tx_input* input) {
    int ret = ::wally_psbt_add_tx_input_at(detail::get_p(psbt), index, flags, input);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_add_tx_output_at(const PSBT& psbt, uint32_t index, uint32_t flags, const struct wally_tx_output* output) {
    int ret = ::wally_psbt_add_tx_output_at(detail::get_p(psbt), index, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_clear_fallback_locktime(struct wally_psbt* psbt) {
    int ret = ::wally_psbt_clear_fallback_locktime(psbt);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_clone_alloc(const PSBT& psbt, uint32_t flags, struct wally_psbt** output) {
    int ret = ::wally_psbt_clone_alloc(detail::get_p(psbt), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_combine(const PSBT& psbt, const struct wally_psbt* source) {
    int ret = ::wally_psbt_combine(detail::get_p(psbt), source);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_extract(const PSBT& psbt, uint32_t flags, struct wally_tx** output) {
    int ret = ::wally_psbt_extract(detail::get_p(psbt), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_finalize(const PSBT& psbt, uint32_t flags) {
    int ret = ::wally_psbt_finalize(detail::get_p(psbt), flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_finalize_input(const PSBT& psbt, size_t index, uint32_t flags) {
    int ret = ::wally_psbt_finalize_input(detail::get_p(psbt), index, flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT, class TXHASH>
inline int psbt_find_input_spending_utxo(const PSBT& psbt, const TXHASH& txhash, uint32_t utxo_index, size_t* written) {
    int ret = ::wally_psbt_find_input_spending_utxo(detail::get_p(psbt), txhash.data(), txhash.size(), utxo_index, written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_free(struct wally_psbt* psbt) {
    int ret = ::wally_psbt_free(psbt);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STR_IN>
inline int psbt_from_base64(const STR_IN& str_in, uint32_t flags, struct wally_psbt** output) {
    int ret = ::wally_psbt_from_base64(detail::get_p(str_in), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STR_IN>
inline int psbt_from_base64_n(const STR_IN& str_in, size_t str_len, uint32_t flags, struct wally_psbt** output) {
    int ret = ::wally_psbt_from_base64_n(detail::get_p(str_in), str_len, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES>
inline int psbt_from_bytes(const BYTES& bytes, uint32_t flags, struct wally_psbt** output) {
    int ret = ::wally_psbt_from_bytes(bytes.data(), bytes.size(), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int psbt_from_tx(const TX& tx, uint32_t version, uint32_t flags, struct wally_psbt** output) {
    int ret = ::wally_psbt_from_tx(detail::get_p(tx), version, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT, class BYTES_OUT>
inline int psbt_get_id(const PSBT& psbt, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_psbt_get_id(detail::get_p(psbt), flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT, class HDKEY>
inline int psbt_get_input_bip32_key_from_alloc(const PSBT& psbt, size_t index, size_t subindex, uint32_t flags, const HDKEY& hdkey, struct ext_key** output) {
    int ret = ::wally_psbt_get_input_bip32_key_from_alloc(detail::get_p(psbt), index, subindex, flags, detail::get_p(hdkey), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT, class SCRIPT, class BYTES_OUT>
inline int psbt_get_input_scriptcode(const PSBT& psbt, size_t index, const SCRIPT& script, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_get_input_scriptcode(detail::get_p(psbt), index, script.data(), script.size(), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT, class SCRIPT>
inline int psbt_get_input_scriptcode_len(const PSBT& psbt, size_t index, const SCRIPT& script, size_t* written) {
    int ret = ::wally_psbt_get_input_scriptcode_len(detail::get_p(psbt), index, script.data(), script.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT, class TX, class SCRIPT, class BYTES_OUT>
inline int psbt_get_input_signature_hash(const PSBT& psbt, size_t index, const TX& tx, const SCRIPT& script, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_psbt_get_input_signature_hash(detail::get_p(psbt), index, detail::get_p(tx), script.data(), script.size(), flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT, class BYTES_OUT>
inline int psbt_get_input_signing_script(const PSBT& psbt, size_t index, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_get_input_signing_script(detail::get_p(psbt), index, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_get_input_signing_script_len(const PSBT& psbt, size_t index, size_t* written) {
    int ret = ::wally_psbt_get_input_signing_script_len(detail::get_p(psbt), index, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_get_length(const PSBT& psbt, uint32_t flags, size_t* written) {
    int ret = ::wally_psbt_get_length(detail::get_p(psbt), flags, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_get_locktime(const PSBT& psbt, size_t* written) {
    int ret = ::wally_psbt_get_locktime(detail::get_p(psbt), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_get_tx_version(const PSBT& psbt, size_t* written) {
    int ret = ::wally_psbt_get_tx_version(detail::get_p(psbt), written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_init_alloc(uint32_t version, size_t inputs_allocation_len, size_t outputs_allocation_len, size_t global_unknowns_allocation_len, uint32_t flags, struct wally_psbt** output) {
    int ret = ::wally_psbt_init_alloc(version, inputs_allocation_len, outputs_allocation_len, global_unknowns_allocation_len, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class PUB_KEY, class SIG>
inline int psbt_input_add_signature(const INPUT& input, const PUB_KEY& pub_key, const SIG& sig) {
    int ret = ::wally_psbt_input_add_signature(detail::get_p(input), pub_key.data(), pub_key.size(), sig.data(), sig.size());
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_required_lockheight(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_required_lockheight(input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_required_locktime(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_required_locktime(input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_sequence(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_sequence(input);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class PUB_KEY>
inline int psbt_input_find_keypath(const INPUT& input, const PUB_KEY& pub_key, size_t* written) {
    int ret = ::wally_psbt_input_find_keypath(detail::get_p(input), pub_key.data(), pub_key.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class PUB_KEY>
inline int psbt_input_find_signature(const INPUT& input, const PUB_KEY& pub_key, size_t* written) {
    int ret = ::wally_psbt_input_find_signature(detail::get_p(input), pub_key.data(), pub_key.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class KEY>
inline int psbt_input_find_unknown(const INPUT& input, const KEY& key, size_t* written) {
    int ret = ::wally_psbt_input_find_unknown(detail::get_p(input), key.data(), key.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_is_finalized(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_is_finalized(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class PUB_KEY, class FINGERPRINT, class CHILD_PATH>
inline int psbt_input_keypath_add(const INPUT& input, const PUB_KEY& pub_key, const FINGERPRINT& fingerprint, const CHILD_PATH& child_path) {
    int ret = ::wally_psbt_input_keypath_add(detail::get_p(input), pub_key.data(), pub_key.size(), fingerprint.data(), fingerprint.size(), child_path.data(), child_path.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class FINAL_SCRIPTSIG>
inline int psbt_input_set_final_scriptsig(const INPUT& input, const FINAL_SCRIPTSIG& final_scriptsig) {
    int ret = ::wally_psbt_input_set_final_scriptsig(detail::get_p(input), final_scriptsig.data(), final_scriptsig.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_final_witness(const INPUT& input, const struct wally_tx_witness_stack* witness) {
    int ret = ::wally_psbt_input_set_final_witness(detail::get_p(input), witness);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_keypaths(const INPUT& input, const struct wally_map* map_in) {
    int ret = ::wally_psbt_input_set_keypaths(detail::get_p(input), map_in);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_output_index(const INPUT& input, uint32_t index) {
    int ret = ::wally_psbt_input_set_output_index(detail::get_p(input), index);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class TXHASH>
inline int psbt_input_set_previous_txid(const INPUT& input, const TXHASH& txhash) {
    int ret = ::wally_psbt_input_set_previous_txid(detail::get_p(input), txhash.data(), txhash.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class SCRIPT>
inline int psbt_input_set_redeem_script(const INPUT& input, const SCRIPT& script) {
    int ret = ::wally_psbt_input_set_redeem_script(detail::get_p(input), script.data(), script.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_required_lockheight(const INPUT& input, uint32_t required_lockheight) {
    int ret = ::wally_psbt_input_set_required_lockheight(detail::get_p(input), required_lockheight);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_required_locktime(const INPUT& input, uint32_t required_locktime) {
    int ret = ::wally_psbt_input_set_required_locktime(detail::get_p(input), required_locktime);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_sequence(const INPUT& input, uint32_t sequence) {
    int ret = ::wally_psbt_input_set_sequence(detail::get_p(input), sequence);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_sighash(const INPUT& input, uint32_t sighash) {
    int ret = ::wally_psbt_input_set_sighash(detail::get_p(input), sighash);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_signatures(const INPUT& input, const struct wally_map* map_in) {
    int ret = ::wally_psbt_input_set_signatures(detail::get_p(input), map_in);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class PUB_KEY>
inline int psbt_input_set_taproot_internal_key(const INPUT& input, const PUB_KEY& pub_key) {
    int ret = ::wally_psbt_input_set_taproot_internal_key(detail::get_p(input), pub_key.data(), pub_key.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class TAP_SIG>
inline int psbt_input_set_taproot_signature(const INPUT& input, const TAP_SIG& tap_sig) {
    int ret = ::wally_psbt_input_set_taproot_signature(detail::get_p(input), tap_sig.data(), tap_sig.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_unknowns(const INPUT& input, const struct wally_map* map_in) {
    int ret = ::wally_psbt_input_set_unknowns(detail::get_p(input), map_in);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_utxo(const INPUT& input, const struct wally_tx* utxo) {
    int ret = ::wally_psbt_input_set_utxo(detail::get_p(input), utxo);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class SCRIPT>
inline int psbt_input_set_witness_script(const INPUT& input, const SCRIPT& script) {
    int ret = ::wally_psbt_input_set_witness_script(detail::get_p(input), script.data(), script.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_witness_utxo(const INPUT& input, const struct wally_tx_output* witness_utxo) {
    int ret = ::wally_psbt_input_set_witness_utxo(detail::get_p(input), witness_utxo);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class UTXO>
inline int psbt_input_set_witness_utxo_from_tx(const INPUT& input, const UTXO& utxo, uint32_t index) {
    int ret = ::wally_psbt_input_set_witness_utxo_from_tx(detail::get_p(input), detail::get_p(utxo), index);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class PUB_KEY, class TAPLEAF_HASHES, class FINGERPRINT, class CHILD_PATH>
inline int psbt_input_taproot_keypath_add(const INPUT& input, const PUB_KEY& pub_key, const TAPLEAF_HASHES& tapleaf_hashes, const FINGERPRINT& fingerprint, const CHILD_PATH& child_path) {
    int ret = ::wally_psbt_input_taproot_keypath_add(detail::get_p(input), pub_key.data(), pub_key.size(), tapleaf_hashes.data(), tapleaf_hashes.size(), fingerprint.data(), fingerprint.size(), child_path.data(), child_path.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_is_elements(const PSBT& psbt, size_t* written) {
    int ret = ::wally_psbt_is_elements(detail::get_p(psbt), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_is_finalized(const PSBT& psbt, size_t* written) {
    int ret = ::wally_psbt_is_finalized(detail::get_p(psbt), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_is_input_finalized(const PSBT& psbt, size_t index, size_t* written) {
    int ret = ::wally_psbt_is_input_finalized(detail::get_p(psbt), index, written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_output_clear_amount(struct wally_psbt_output* output) {
    int ret = ::wally_psbt_output_clear_amount(output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class PUB_KEY>
inline int psbt_output_find_keypath(const OUTPUT& output, const PUB_KEY& pub_key, size_t* written) {
    int ret = ::wally_psbt_output_find_keypath(detail::get_p(output), pub_key.data(), pub_key.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class KEY>
inline int psbt_output_find_unknown(const OUTPUT& output, const KEY& key, size_t* written) {
    int ret = ::wally_psbt_output_find_unknown(detail::get_p(output), key.data(), key.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class PUB_KEY, class FINGERPRINT, class CHILD_PATH>
inline int psbt_output_keypath_add(const OUTPUT& output, const PUB_KEY& pub_key, const FINGERPRINT& fingerprint, const CHILD_PATH& child_path) {
    int ret = ::wally_psbt_output_keypath_add(detail::get_p(output), pub_key.data(), pub_key.size(), fingerprint.data(), fingerprint.size(), child_path.data(), child_path.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT>
inline int psbt_output_set_amount(const OUTPUT& output, uint64_t amount) {
    int ret = ::wally_psbt_output_set_amount(detail::get_p(output), amount);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT>
inline int psbt_output_set_keypaths(const OUTPUT& output, const struct wally_map* map_in) {
    int ret = ::wally_psbt_output_set_keypaths(detail::get_p(output), map_in);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class SCRIPT>
inline int psbt_output_set_redeem_script(const OUTPUT& output, const SCRIPT& script) {
    int ret = ::wally_psbt_output_set_redeem_script(detail::get_p(output), script.data(), script.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class SCRIPT>
inline int psbt_output_set_script(const OUTPUT& output, const SCRIPT& script) {
    int ret = ::wally_psbt_output_set_script(detail::get_p(output), script.data(), script.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class PUB_KEY>
inline int psbt_output_set_taproot_internal_key(const OUTPUT& output, const PUB_KEY& pub_key) {
    int ret = ::wally_psbt_output_set_taproot_internal_key(detail::get_p(output), pub_key.data(), pub_key.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT>
inline int psbt_output_set_unknowns(const OUTPUT& output, const struct wally_map* map_in) {
    int ret = ::wally_psbt_output_set_unknowns(detail::get_p(output), map_in);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class SCRIPT>
inline int psbt_output_set_witness_script(const OUTPUT& output, const SCRIPT& script) {
    int ret = ::wally_psbt_output_set_witness_script(detail::get_p(output), script.data(), script.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class PUB_KEY, class TAPLEAF_HASHES, class FINGERPRINT, class CHILD_PATH>
inline int psbt_output_taproot_keypath_add(const OUTPUT& output, const PUB_KEY& pub_key, const TAPLEAF_HASHES& tapleaf_hashes, const FINGERPRINT& fingerprint, const CHILD_PATH& child_path) {
    int ret = ::wally_psbt_output_taproot_keypath_add(detail::get_p(output), pub_key.data(), pub_key.size(), tapleaf_hashes.data(), tapleaf_hashes.size(), fingerprint.data(), fingerprint.size(), child_path.data(), child_path.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_remove_input(const PSBT& psbt, uint32_t index) {
    int ret = ::wally_psbt_remove_input(detail::get_p(psbt), index);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_remove_output(const PSBT& psbt, uint32_t index) {
    int ret = ::wally_psbt_remove_output(detail::get_p(psbt), index);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_set_fallback_locktime(const PSBT& psbt, uint32_t locktime) {
    int ret = ::wally_psbt_set_fallback_locktime(detail::get_p(psbt), locktime);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_set_global_tx(const PSBT& psbt, const struct wally_tx* tx) {
    int ret = ::wally_psbt_set_global_tx(detail::get_p(psbt), tx);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_set_tx_modifiable_flags(const PSBT& psbt, uint32_t flags) {
    int ret = ::wally_psbt_set_tx_modifiable_flags(detail::get_p(psbt), flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_set_tx_version(const PSBT& psbt, uint32_t version) {
    int ret = ::wally_psbt_set_tx_version(detail::get_p(psbt), version);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_set_version(const PSBT& psbt, uint32_t flags, uint32_t version) {
    int ret = ::wally_psbt_set_version(detail::get_p(psbt), flags, version);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT, class KEY>
inline int psbt_sign(const PSBT& psbt, const KEY& key, uint32_t flags) {
    int ret = ::wally_psbt_sign(detail::get_p(psbt), key.data(), key.size(), flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT, class HDKEY>
inline int psbt_sign_bip32(const PSBT& psbt, const HDKEY& hdkey, uint32_t flags) {
    int ret = ::wally_psbt_sign_bip32(detail::get_p(psbt), detail::get_p(hdkey), flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT, class TXHASH, class HDKEY>
inline int psbt_sign_input_bip32(const PSBT& psbt, size_t index, size_t subindex, const TXHASH& txhash, const HDKEY& hdkey, uint32_t flags) {
    int ret = ::wally_psbt_sign_input_bip32(detail::get_p(psbt), index, subindex, txhash.data(), txhash.size(), detail::get_p(hdkey), flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_to_base64(const PSBT& psbt, uint32_t flags, char** output) {
    int ret = ::wally_psbt_to_base64(detail::get_p(psbt), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT, class BYTES_OUT>
inline int psbt_to_bytes(const PSBT& psbt, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_to_bytes(detail::get_p(psbt), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int ripemd160(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_ripemd160(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SIG, class S2C_DATA, class S2C_OPENING>
inline bool s2c_commitment_verify(const SIG& sig, const S2C_DATA& s2c_data, const S2C_OPENING& s2c_opening, uint32_t flags) {
    int ret = ::wally_s2c_commitment_verify(sig.data(), sig.size(), s2c_data.data(), s2c_data.size(), s2c_opening.data(), s2c_opening.size(), flags);
    return ret == WALLY_OK;
}

template <class PRIV_KEY, class BYTES, class S2C_DATA, class S2C_OPENING_OUT, class BYTES_OUT>
inline int s2c_sig_from_bytes(const PRIV_KEY& priv_key, const BYTES& bytes, const S2C_DATA& s2c_data, uint32_t flags, S2C_OPENING_OUT& s2c_opening_out, BYTES_OUT& bytes_out) {
    int ret = ::wally_s2c_sig_from_bytes(priv_key.data(), priv_key.size(), bytes.data(), bytes.size(), s2c_data.data(), s2c_data.size(), flags, s2c_opening_out.data(), s2c_opening_out.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int script_push_from_bytes(const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_script_push_from_bytes(bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int scriptpubkey_csv_2of2_then_1_from_bytes(const BYTES& bytes, uint32_t csv_blocks, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_scriptpubkey_csv_2of2_then_1_from_bytes(bytes.data(), bytes.size(), csv_blocks, flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int scriptpubkey_csv_2of2_then_1_from_bytes_opt(const BYTES& bytes, uint32_t csv_blocks, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_scriptpubkey_csv_2of2_then_1_from_bytes_opt(bytes.data(), bytes.size(), csv_blocks, flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES>
inline int scriptpubkey_csv_blocks_from_csv_2of2_then_1(const BYTES& bytes, uint32_t* value_out) {
    int ret = ::wally_scriptpubkey_csv_blocks_from_csv_2of2_then_1(bytes.data(), bytes.size(), value_out);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES>
inline int scriptpubkey_get_type(const BYTES& bytes, size_t* written) {
    int ret = ::wally_scriptpubkey_get_type(bytes.data(), bytes.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int scriptpubkey_multisig_from_bytes(const BYTES& bytes, uint32_t threshold, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_scriptpubkey_multisig_from_bytes(bytes.data(), bytes.size(), threshold, flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int scriptpubkey_op_return_from_bytes(const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_scriptpubkey_op_return_from_bytes(bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int scriptpubkey_p2pkh_from_bytes(const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_scriptpubkey_p2pkh_from_bytes(bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int scriptpubkey_p2sh_from_bytes(const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_scriptpubkey_p2sh_from_bytes(bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int scriptpubkey_p2tr_from_bytes(const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_scriptpubkey_p2tr_from_bytes(bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SCRIPTPUBKEY>
inline int scriptpubkey_to_address(const SCRIPTPUBKEY& scriptpubkey, uint32_t network, char** output) {
    int ret = ::wally_scriptpubkey_to_address(scriptpubkey.data(), scriptpubkey.size(), network, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SCRIPT, class BYTES, class SIGHASH, class BYTES_OUT>
inline int scriptsig_multisig_from_bytes(const SCRIPT& script, const BYTES& bytes, const SIGHASH& sighash, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_scriptsig_multisig_from_bytes(script.data(), script.size(), bytes.data(), bytes.size(), sighash.data(), sighash.size(), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PUB_KEY, class SIG, class BYTES_OUT>
inline int scriptsig_p2pkh_from_der(const PUB_KEY& pub_key, const SIG& sig, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_scriptsig_p2pkh_from_der(pub_key.data(), pub_key.size(), sig.data(), sig.size(), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PUB_KEY, class SIG, class BYTES_OUT>
inline int scriptsig_p2pkh_from_sig(const PUB_KEY& pub_key, const SIG& sig, uint32_t sighash, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_scriptsig_p2pkh_from_sig(pub_key.data(), pub_key.size(), sig.data(), sig.size(), sighash, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PASS, class SALT, class BYTES_OUT>
inline int scrypt(const PASS& pass, const SALT& salt, uint32_t cost, uint32_t block_size, uint32_t parallelism, BYTES_OUT& bytes_out) {
    int ret = ::wally_scrypt(pass.data(), pass.size(), salt.data(), salt.size(), cost, block_size, parallelism, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES>
inline int secp_randomize(const BYTES& bytes) {
    int ret = ::wally_secp_randomize(bytes.data(), bytes.size());
    return detail::check_ret(__FUNCTION__, ret);
}

inline int set_operations(const struct wally_operations* ops) {
    int ret = ::wally_set_operations(ops);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int sha256(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_sha256(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int sha256_midstate(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_sha256_midstate(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int sha256d(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_sha256d(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int sha512(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_sha512(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class LABEL, class BYTES_OUT>
inline int symmetric_key_from_parent(const BYTES& bytes, uint32_t version, const LABEL& label, BYTES_OUT& bytes_out) {
    int ret = ::wally_symmetric_key_from_parent(bytes.data(), bytes.size(), version, label.data(), label.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int symmetric_key_from_seed(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_symmetric_key_from_seed(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_add_input(const TX& tx, const struct wally_tx_input* input) {
    int ret = ::wally_tx_add_input(detail::get_p(tx), input);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_add_input_at(const TX& tx, uint32_t index, const struct wally_tx_input* input) {
    int ret = ::wally_tx_add_input_at(detail::get_p(tx), index, input);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_add_output(const TX& tx, const struct wally_tx_output* output) {
    int ret = ::wally_tx_add_output(detail::get_p(tx), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_add_output_at(const TX& tx, uint32_t index, const struct wally_tx_output* output) {
    int ret = ::wally_tx_add_output_at(detail::get_p(tx), index, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX, class TXHASH, class SCRIPT, class WITNESS>
inline int tx_add_raw_input(const TX& tx, const TXHASH& txhash, uint32_t utxo_index, uint32_t sequence, const SCRIPT& script, const WITNESS& witness, uint32_t flags) {
    int ret = ::wally_tx_add_raw_input(detail::get_p(tx), txhash.data(), txhash.size(), utxo_index, sequence, script.data(), script.size(), detail::get_p(witness), flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX, class TXHASH, class SCRIPT, class WITNESS>
inline int tx_add_raw_input_at(const TX& tx, uint32_t index, const TXHASH& txhash, uint32_t utxo_index, uint32_t sequence, const SCRIPT& script, const WITNESS& witness, uint32_t flags) {
    int ret = ::wally_tx_add_raw_input_at(detail::get_p(tx), index, txhash.data(), txhash.size(), utxo_index, sequence, script.data(), script.size(), detail::get_p(witness), flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX, class SCRIPT>
inline int tx_add_raw_output(const TX& tx, uint64_t satoshi, const SCRIPT& script, uint32_t flags) {
    int ret = ::wally_tx_add_raw_output(detail::get_p(tx), satoshi, script.data(), script.size(), flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX, class SCRIPT>
inline int tx_add_raw_output_at(const TX& tx, uint32_t index, uint64_t satoshi, const SCRIPT& script, uint32_t flags) {
    int ret = ::wally_tx_add_raw_output_at(detail::get_p(tx), index, satoshi, script.data(), script.size(), flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_clone_alloc(const TX& tx, uint32_t flags, struct wally_tx** output) {
    int ret = ::wally_tx_clone_alloc(detail::get_p(tx), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int tx_free(struct wally_tx* tx) {
    int ret = ::wally_tx_free(tx);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES>
inline int tx_from_bytes(const BYTES& bytes, uint32_t flags, struct wally_tx** output) {
    int ret = ::wally_tx_from_bytes(bytes.data(), bytes.size(), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HEX>
inline int tx_from_hex(const HEX& hex, uint32_t flags, struct wally_tx** output) {
    int ret = ::wally_tx_from_hex(detail::get_p(hex), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX, class SCRIPT, class BYTES_OUT>
inline int tx_get_btc_signature_hash(const TX& tx, size_t index, const SCRIPT& script, uint64_t satoshi, uint32_t sighash, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_get_btc_signature_hash(detail::get_p(tx), index, script.data(), script.size(), satoshi, sighash, flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX, class SCRIPTS, class VALUES, class TAPLEAF_SCRIPT, class ANNEX, class BYTES_OUT>
inline int tx_get_btc_taproot_signature_hash(const TX& tx, size_t index, const SCRIPTS& scripts, const VALUES& values, const TAPLEAF_SCRIPT& tapleaf_script, uint32_t key_version, uint32_t codesep_position, const ANNEX& annex, uint32_t sighash, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_get_btc_taproot_signature_hash(detail::get_p(tx), index, detail::get_p(scripts), values.data(), values.size(), tapleaf_script.data(), tapleaf_script.size(), key_version, codesep_position, annex.data(), annex.size(), sighash, flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX, class BYTES_OUT>
inline int tx_get_hash_prevouts(const TX& tx, size_t index, size_t num_inputs, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_get_hash_prevouts(detail::get_p(tx), index, num_inputs, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_get_length(const TX& tx, uint32_t flags, size_t* written) {
    int ret = ::wally_tx_get_length(detail::get_p(tx), flags, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX, class SCRIPT, class EXTRA, class BYTES_OUT>
inline int tx_get_signature_hash(const TX& tx, size_t index, const SCRIPT& script, const EXTRA& extra, uint32_t extra_offset, uint64_t satoshi, uint32_t sighash, uint32_t tx_sighash, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_get_signature_hash(detail::get_p(tx), index, script.data(), script.size(), extra.data(), extra.size(), extra_offset, satoshi, sighash, tx_sighash, flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_get_total_output_satoshi(const TX& tx, uint64_t* value_out) {
    int ret = ::wally_tx_get_total_output_satoshi(detail::get_p(tx), value_out);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX, class BYTES_OUT>
inline int tx_get_txid(const TX& tx, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_get_txid(detail::get_p(tx), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_get_vsize(const TX& tx, size_t* written) {
    int ret = ::wally_tx_get_vsize(detail::get_p(tx), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_get_weight(const TX& tx, size_t* written) {
    int ret = ::wally_tx_get_weight(detail::get_p(tx), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_get_witness_count(const TX& tx, size_t* written) {
    int ret = ::wally_tx_get_witness_count(detail::get_p(tx), written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int tx_init_alloc(uint32_t version, uint32_t locktime, size_t inputs_allocation_len, size_t outputs_allocation_len, struct wally_tx** output) {
    int ret = ::wally_tx_init_alloc(version, locktime, inputs_allocation_len, outputs_allocation_len, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX_INPUT_IN>
inline int tx_input_clone(const TX_INPUT_IN& tx_input_in, struct wally_tx_input* input) {
    int ret = ::wally_tx_input_clone(detail::get_p(tx_input_in), input);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX_INPUT_IN>
inline int tx_input_clone_alloc(const TX_INPUT_IN& tx_input_in, struct wally_tx_input** input) {
    int ret = ::wally_tx_input_clone_alloc(detail::get_p(tx_input_in), input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int tx_input_free(struct wally_tx_input* input) {
    int ret = ::wally_tx_input_free(input);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TXHASH, class SCRIPT, class WITNESS>
inline int tx_input_init_alloc(const TXHASH& txhash, uint32_t utxo_index, uint32_t sequence, const SCRIPT& script, const WITNESS& witness, struct wally_tx_input** output) {
    int ret = ::wally_tx_input_init_alloc(txhash.data(), txhash.size(), utxo_index, sequence, script.data(), script.size(), detail::get_p(witness), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_is_coinbase(const TX& tx, size_t* written) {
    int ret = ::wally_tx_is_coinbase(detail::get_p(tx), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX_OUTPUT_IN>
inline int tx_output_clone(const TX_OUTPUT_IN& tx_output_in, struct wally_tx_output* output) {
    int ret = ::wally_tx_output_clone(detail::get_p(tx_output_in), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX_OUTPUT_IN>
inline int tx_output_clone_alloc(const TX_OUTPUT_IN& tx_output_in, struct wally_tx_output** output) {
    int ret = ::wally_tx_output_clone_alloc(detail::get_p(tx_output_in), output);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int tx_output_free(struct wally_tx_output* output) {
    int ret = ::wally_tx_output_free(output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SCRIPT>
inline int tx_output_init(uint64_t satoshi, const SCRIPT& script, struct wally_tx_output* output) {
    int ret = ::wally_tx_output_init(satoshi, script.data(), script.size(), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SCRIPT>
inline int tx_output_init_alloc(uint64_t satoshi, const SCRIPT& script, struct wally_tx_output** output) {
    int ret = ::wally_tx_output_init_alloc(satoshi, script.data(), script.size(), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_remove_input(const TX& tx, size_t index) {
    int ret = ::wally_tx_remove_input(detail::get_p(tx), index);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_remove_output(const TX& tx, size_t index) {
    int ret = ::wally_tx_remove_output(detail::get_p(tx), index);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX, class SCRIPT>
inline int tx_set_input_script(const TX& tx, size_t index, const SCRIPT& script) {
    int ret = ::wally_tx_set_input_script(detail::get_p(tx), index, script.data(), script.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_set_input_witness(const TX& tx, size_t index, const struct wally_tx_witness_stack* stack) {
    int ret = ::wally_tx_set_input_witness(detail::get_p(tx), index, stack);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX, class BYTES_OUT>
inline int tx_to_bytes(const TX& tx, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_tx_to_bytes(detail::get_p(tx), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_to_hex(const TX& tx, uint32_t flags, char** output) {
    int ret = ::wally_tx_to_hex(detail::get_p(tx), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int tx_vsize_from_weight(size_t weight, size_t* written) {
    int ret = ::wally_tx_vsize_from_weight(weight, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STACK, class WITNESS>
inline int tx_witness_stack_add(const STACK& stack, const WITNESS& witness) {
    int ret = ::wally_tx_witness_stack_add(detail::get_p(stack), witness.data(), witness.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STACK>
inline int tx_witness_stack_add_dummy(const STACK& stack, uint32_t flags) {
    int ret = ::wally_tx_witness_stack_add_dummy(detail::get_p(stack), flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STACK>
inline int tx_witness_stack_clone_alloc(const STACK& stack, struct wally_tx_witness_stack** output) {
    int ret = ::wally_tx_witness_stack_clone_alloc(detail::get_p(stack), output);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int tx_witness_stack_free(struct wally_tx_witness_stack* stack) {
    int ret = ::wally_tx_witness_stack_free(stack);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES>
inline int tx_witness_stack_from_bytes(const BYTES& bytes, struct wally_tx_witness_stack** output) {
    int ret = ::wally_tx_witness_stack_from_bytes(bytes.data(), bytes.size(), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STACK>
inline int tx_witness_stack_get_length(const STACK& stack, size_t* written) {
    int ret = ::wally_tx_witness_stack_get_length(detail::get_p(stack), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STACK>
inline int tx_witness_stack_get_num_items(const STACK& stack, size_t* written) {
    int ret = ::wally_tx_witness_stack_get_num_items(detail::get_p(stack), written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int tx_witness_stack_init_alloc(size_t allocation_len, struct wally_tx_witness_stack** output) {
    int ret = ::wally_tx_witness_stack_init_alloc(allocation_len, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STACK, class WITNESS>
inline int tx_witness_stack_set(const STACK& stack, size_t index, const WITNESS& witness) {
    int ret = ::wally_tx_witness_stack_set(detail::get_p(stack), index, witness.data(), witness.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STACK>
inline int tx_witness_stack_set_dummy(const STACK& stack, size_t index, uint32_t flags) {
    int ret = ::wally_tx_witness_stack_set_dummy(detail::get_p(stack), index, flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class STACK, class BYTES_OUT>
inline int tx_witness_stack_to_bytes(const STACK& stack, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_tx_witness_stack_to_bytes(detail::get_p(stack), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES>
inline int varbuff_get_length(const BYTES& bytes, size_t* written) {
    int ret = ::wally_varbuff_get_length(bytes.data(), bytes.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int varbuff_to_bytes(const BYTES& bytes, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_varbuff_to_bytes(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int varint_get_length(uint64_t value, size_t* written) {
    int ret = ::wally_varint_get_length(value, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES_OUT>
inline int varint_to_bytes(uint64_t value, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_varint_to_bytes(value, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PRIV_KEY>
inline int wif_from_bytes(const PRIV_KEY& priv_key, uint32_t prefix, uint32_t flags, char** output) {
    int ret = ::wally_wif_from_bytes(priv_key.data(), priv_key.size(), prefix, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class WIF>
inline int wif_is_uncompressed(const WIF& wif, size_t* written) {
    int ret = ::wally_wif_is_uncompressed(detail::get_p(wif), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class WIF>
inline int wif_to_address(const WIF& wif, uint32_t prefix, uint32_t version, char** output) {
    int ret = ::wally_wif_to_address(detail::get_p(wif), prefix, version, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class WIF, class BYTES_OUT>
inline int wif_to_bytes(const WIF& wif, uint32_t prefix, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_wif_to_bytes(detail::get_p(wif), prefix, flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class WIF, class BYTES_OUT>
inline int wif_to_public_key(const WIF& wif, uint32_t prefix, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_wif_to_public_key(detail::get_p(wif), prefix, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SCRIPT, class BYTES, class SIGHASH>
inline int witness_multisig_from_bytes(const SCRIPT& script, const BYTES& bytes, const SIGHASH& sighash, uint32_t flags, struct wally_tx_witness_stack** witness) {
    int ret = ::wally_witness_multisig_from_bytes(script.data(), script.size(), bytes.data(), bytes.size(), sighash.data(), sighash.size(), flags, witness);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SIG>
inline int witness_p2tr_from_sig(const SIG& sig, struct wally_tx_witness_stack** witness) {
    int ret = ::wally_witness_p2tr_from_sig(sig.data(), sig.size(), witness);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PUB_KEY, class SIG>
inline int witness_p2wpkh_from_der(const PUB_KEY& pub_key, const SIG& sig, struct wally_tx_witness_stack** witness) {
    int ret = ::wally_witness_p2wpkh_from_der(pub_key.data(), pub_key.size(), sig.data(), sig.size(), witness);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PUB_KEY, class SIG>
inline int witness_p2wpkh_from_sig(const PUB_KEY& pub_key, const SIG& sig, uint32_t sighash, struct wally_tx_witness_stack** witness) {
    int ret = ::wally_witness_p2wpkh_from_sig(pub_key.data(), pub_key.size(), sig.data(), sig.size(), sighash, witness);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int witness_program_from_bytes(const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_witness_program_from_bytes(bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int witness_program_from_bytes_and_version(const BYTES& bytes, uint32_t version, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_witness_program_from_bytes_and_version(bytes.data(), bytes.size(), version, flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

#ifndef WALLY_ABI_NO_ELEMENTS
template <class HDKEY, class CHILD_PATH>
inline int bip32_key_with_tweak_from_parent_path(const HDKEY& hdkey, const CHILD_PATH& child_path, uint32_t flags, struct ext_key* output) {
    int ret = ::bip32_key_with_tweak_from_parent_path(detail::get_p(hdkey), child_path.data(), child_path.size(), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class HDKEY, class CHILD_PATH>
inline int bip32_key_with_tweak_from_parent_path_alloc(const HDKEY& hdkey, const CHILD_PATH& child_path, uint32_t flags, struct ext_key** output) {
    int ret = ::bip32_key_with_tweak_from_parent_path_alloc(detail::get_p(hdkey), child_path.data(), child_path.size(), flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class BYTES_OUT>
inline int asset_blinding_key_from_seed(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_asset_blinding_key_from_seed(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class HASH_PREVOUTS, class BYTES_OUT>
inline int asset_blinding_key_to_abf(const BYTES& bytes, const HASH_PREVOUTS& hash_prevouts, uint32_t output_index, BYTES_OUT& bytes_out) {
    int ret = ::wally_asset_blinding_key_to_abf(bytes.data(), bytes.size(), hash_prevouts.data(), hash_prevouts.size(), output_index, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class HASH_PREVOUTS, class BYTES_OUT>
inline int asset_blinding_key_to_abf_vbf(const BYTES& bytes, const HASH_PREVOUTS& hash_prevouts, uint32_t output_index, BYTES_OUT& bytes_out) {
    int ret = ::wally_asset_blinding_key_to_abf_vbf(bytes.data(), bytes.size(), hash_prevouts.data(), hash_prevouts.size(), output_index, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class SCRIPT, class BYTES_OUT>
inline int asset_blinding_key_to_ec_private_key(const BYTES& bytes, const SCRIPT& script, BYTES_OUT& bytes_out) {
    int ret = ::wally_asset_blinding_key_to_ec_private_key(bytes.data(), bytes.size(), script.data(), script.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES, class HASH_PREVOUTS, class BYTES_OUT>
inline int asset_blinding_key_to_vbf(const BYTES& bytes, const HASH_PREVOUTS& hash_prevouts, uint32_t output_index, BYTES_OUT& bytes_out) {
    int ret = ::wally_asset_blinding_key_to_vbf(bytes.data(), bytes.size(), hash_prevouts.data(), hash_prevouts.size(), output_index, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class VALUES, class ABF, class VBF, class BYTES_OUT>
inline int asset_final_vbf(const VALUES& values, size_t num_inputs, const ABF& abf, const VBF& vbf, BYTES_OUT& bytes_out) {
    int ret = ::wally_asset_final_vbf(values.data(), values.size(), num_inputs, abf.data(), abf.size(), vbf.data(), vbf.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ASSET, class ABF, class BYTES_OUT>
inline int asset_generator_from_bytes(const ASSET& asset, const ABF& abf, BYTES_OUT& bytes_out) {
    int ret = ::wally_asset_generator_from_bytes(asset.data(), asset.size(), abf.data(), abf.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ONLINE_KEYS, class OFFLINE_KEYS, class SUB_PUBKEY, class ONLINE_PRIV_KEY, class SUMMED_KEY, class BYTES_OUT>
inline int asset_pak_whitelistproof(const ONLINE_KEYS& online_keys, const OFFLINE_KEYS& offline_keys, size_t key_index, const SUB_PUBKEY& sub_pubkey, const ONLINE_PRIV_KEY& online_priv_key, const SUMMED_KEY& summed_key, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_asset_pak_whitelistproof(online_keys.data(), online_keys.size(), offline_keys.data(), offline_keys.size(), key_index, sub_pubkey.data(), sub_pubkey.size(), online_priv_key.data(), online_priv_key.size(), summed_key.data(), summed_key.size(), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ONLINE_KEYS, class OFFLINE_KEYS, class SUB_PUBKEY, class ONLINE_PRIV_KEY, class SUMMED_KEY>
inline int asset_pak_whitelistproof_len(const ONLINE_KEYS& online_keys, const OFFLINE_KEYS& offline_keys, size_t key_index, const SUB_PUBKEY& sub_pubkey, const ONLINE_PRIV_KEY& online_priv_key, const SUMMED_KEY& summed_key, size_t* written) {
    int ret = ::wally_asset_pak_whitelistproof_len(online_keys.data(), online_keys.size(), offline_keys.data(), offline_keys.size(), key_index, sub_pubkey.data(), sub_pubkey.size(), online_priv_key.data(), online_priv_key.size(), summed_key.data(), summed_key.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int asset_pak_whitelistproof_size(size_t num_keys, size_t* written) {
    int ret = ::wally_asset_pak_whitelistproof_size(num_keys, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PUB_KEY, class PRIV_KEY, class ASSET, class ABF, class VBF, class COMMITMENT, class EXTRA, class GENERATOR, class BYTES_OUT>
inline int asset_rangeproof(uint64_t value, const PUB_KEY& pub_key, const PRIV_KEY& priv_key, const ASSET& asset, const ABF& abf, const VBF& vbf, const COMMITMENT& commitment, const EXTRA& extra, const GENERATOR& generator, uint64_t min_value, int exp, int min_bits, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_asset_rangeproof(value, pub_key.data(), pub_key.size(), priv_key.data(), priv_key.size(), asset.data(), asset.size(), abf.data(), abf.size(), vbf.data(), vbf.size(), commitment.data(), commitment.size(), extra.data(), extra.size(), generator.data(), generator.size(), min_value, exp, min_bits, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int asset_rangeproof_get_maximum_len(uint64_t value, int min_bits, size_t* written) {
    int ret = ::wally_asset_rangeproof_get_maximum_len(value, min_bits, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class NONCE_HASH, class ASSET, class ABF, class VBF, class COMMITMENT, class EXTRA, class GENERATOR, class BYTES_OUT>
inline int asset_rangeproof_with_nonce(uint64_t value, const NONCE_HASH& nonce_hash, const ASSET& asset, const ABF& abf, const VBF& vbf, const COMMITMENT& commitment, const EXTRA& extra, const GENERATOR& generator, uint64_t min_value, int exp, int min_bits, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_asset_rangeproof_with_nonce(value, nonce_hash.data(), nonce_hash.size(), asset.data(), asset.size(), abf.data(), abf.size(), vbf.data(), vbf.size(), commitment.data(), commitment.size(), extra.data(), extra.size(), generator.data(), generator.size(), min_value, exp, min_bits, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ABF, class VBF, class BYTES_OUT>
inline int asset_scalar_offset(uint64_t value, const ABF& abf, const VBF& vbf, BYTES_OUT& bytes_out) {
    int ret = ::wally_asset_scalar_offset(value, abf.data(), abf.size(), vbf.data(), vbf.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT_ASSET, class OUTPUT_ABF, class OUTPUT_GENERATOR, class BYTES, class ASSET, class ABF, class GENERATOR, class BYTES_OUT>
inline int asset_surjectionproof(const OUTPUT_ASSET& output_asset, const OUTPUT_ABF& output_abf, const OUTPUT_GENERATOR& output_generator, const BYTES& bytes, const ASSET& asset, const ABF& abf, const GENERATOR& generator, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_asset_surjectionproof(output_asset.data(), output_asset.size(), output_abf.data(), output_abf.size(), output_generator.data(), output_generator.size(), bytes.data(), bytes.size(), asset.data(), asset.size(), abf.data(), abf.size(), generator.data(), generator.size(), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT_ASSET, class OUTPUT_ABF, class OUTPUT_GENERATOR, class BYTES, class ASSET, class ABF, class GENERATOR>
inline int asset_surjectionproof_len(const OUTPUT_ASSET& output_asset, const OUTPUT_ABF& output_abf, const OUTPUT_GENERATOR& output_generator, const BYTES& bytes, const ASSET& asset, const ABF& abf, const GENERATOR& generator, size_t* written) {
    int ret = ::wally_asset_surjectionproof_len(output_asset.data(), output_asset.size(), output_abf.data(), output_abf.size(), output_generator.data(), output_generator.size(), bytes.data(), bytes.size(), asset.data(), asset.size(), abf.data(), abf.size(), generator.data(), generator.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int asset_surjectionproof_size(size_t num_inputs, size_t* written) {
    int ret = ::wally_asset_surjectionproof_size(num_inputs, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PUB_KEY, class PRIV_KEY, class PROOF, class COMMITMENT, class EXTRA, class GENERATOR, class ASSET_OUT, class ABF_OUT, class VBF_OUT>
inline int asset_unblind(const PUB_KEY& pub_key, const PRIV_KEY& priv_key, const PROOF& proof, const COMMITMENT& commitment, const EXTRA& extra, const GENERATOR& generator, ASSET_OUT& asset_out, ABF_OUT& abf_out, VBF_OUT& vbf_out, uint64_t* value_out) {
    int ret = ::wally_asset_unblind(pub_key.data(), pub_key.size(), priv_key.data(), priv_key.size(), proof.data(), proof.size(), commitment.data(), commitment.size(), extra.data(), extra.size(), generator.data(), generator.size(), asset_out.data(), asset_out.size(), abf_out.data(), abf_out.size(), vbf_out.data(), vbf_out.size(), value_out);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class NONCE_HASH, class PROOF, class COMMITMENT, class EXTRA, class GENERATOR, class ASSET_OUT, class ABF_OUT, class VBF_OUT>
inline int asset_unblind_with_nonce(const NONCE_HASH& nonce_hash, const PROOF& proof, const COMMITMENT& commitment, const EXTRA& extra, const GENERATOR& generator, ASSET_OUT& asset_out, ABF_OUT& abf_out, VBF_OUT& vbf_out, uint64_t* value_out) {
    int ret = ::wally_asset_unblind_with_nonce(nonce_hash.data(), nonce_hash.size(), proof.data(), proof.size(), commitment.data(), commitment.size(), extra.data(), extra.size(), generator.data(), generator.size(), asset_out.data(), asset_out.size(), abf_out.data(), abf_out.size(), vbf_out.data(), vbf_out.size(), value_out);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class VBF, class GENERATOR, class BYTES_OUT>
inline int asset_value_commitment(uint64_t value, const VBF& vbf, const GENERATOR& generator, BYTES_OUT& bytes_out) {
    int ret = ::wally_asset_value_commitment(value, vbf.data(), vbf.size(), generator.data(), generator.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class VALUES>
inline int coinselect_assets(const VALUES& values, uint64_t target, uint64_t attempts, uint32_t io_ratio, uint32_t* indices_out, size_t indices_out_len, size_t* written) {
    int ret = ::wally_coinselect_assets(values.data(), values.size(), target, attempts, io_ratio, indices_out, indices_out_len, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ADDRESS, class PUB_KEY>
inline int confidential_addr_from_addr(const ADDRESS& address, uint32_t prefix, const PUB_KEY& pub_key, char** output) {
    int ret = ::wally_confidential_addr_from_addr(detail::get_p(address), prefix, pub_key.data(), pub_key.size(), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ADDRESS, class ADDR_FAMILY, class CONFIDENTIAL_ADDR_FAMILY, class PUB_KEY>
inline int confidential_addr_from_addr_segwit(const ADDRESS& address, const ADDR_FAMILY& addr_family, const CONFIDENTIAL_ADDR_FAMILY& confidential_addr_family, const PUB_KEY& pub_key, char** output) {
    int ret = ::wally_confidential_addr_from_addr_segwit(detail::get_p(address), detail::get_p(addr_family), detail::get_p(confidential_addr_family), pub_key.data(), pub_key.size(), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ADDRESS, class CONFIDENTIAL_ADDR_FAMILY, class BYTES_OUT>
inline int confidential_addr_segwit_to_ec_public_key(const ADDRESS& address, const CONFIDENTIAL_ADDR_FAMILY& confidential_addr_family, BYTES_OUT& bytes_out) {
    int ret = ::wally_confidential_addr_segwit_to_ec_public_key(detail::get_p(address), detail::get_p(confidential_addr_family), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ADDRESS>
inline int confidential_addr_to_addr(const ADDRESS& address, uint32_t prefix, char** output) {
    int ret = ::wally_confidential_addr_to_addr(detail::get_p(address), prefix, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ADDRESS, class CONFIDENTIAL_ADDR_FAMILY, class ADDR_FAMILY>
inline int confidential_addr_to_addr_segwit(const ADDRESS& address, const CONFIDENTIAL_ADDR_FAMILY& confidential_addr_family, const ADDR_FAMILY& addr_family, char** output) {
    int ret = ::wally_confidential_addr_to_addr_segwit(detail::get_p(address), detail::get_p(confidential_addr_family), detail::get_p(addr_family), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ADDRESS, class BYTES_OUT>
inline int confidential_addr_to_ec_public_key(const ADDRESS& address, uint32_t prefix, BYTES_OUT& bytes_out) {
    int ret = ::wally_confidential_addr_to_ec_public_key(detail::get_p(address), prefix, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PUB_KEY, class PRIV_KEY, class BYTES_OUT>
inline int ecdh_nonce_hash(const PUB_KEY& pub_key, const PRIV_KEY& priv_key, BYTES_OUT& bytes_out) {
    int ret = ::wally_ecdh_nonce_hash(pub_key.data(), pub_key.size(), priv_key.data(), priv_key.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class REDEEM_SCRIPT, class SCRIPT, class BYTES_OUT>
inline int elements_pegin_contract_script_from_bytes(const REDEEM_SCRIPT& redeem_script, const SCRIPT& script, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_elements_pegin_contract_script_from_bytes(redeem_script.data(), redeem_script.size(), script.data(), script.size(), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class GENESIS_BLOCKHASH, class MAINCHAIN_SCRIPT, class SUB_PUBKEY, class WHITELISTPROOF, class BYTES_OUT>
inline int elements_pegout_script_from_bytes(const GENESIS_BLOCKHASH& genesis_blockhash, const MAINCHAIN_SCRIPT& mainchain_script, const SUB_PUBKEY& sub_pubkey, const WHITELISTPROOF& whitelistproof, uint32_t flags, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_elements_pegout_script_from_bytes(genesis_blockhash.data(), genesis_blockhash.size(), mainchain_script.data(), mainchain_script.size(), sub_pubkey.data(), sub_pubkey.size(), whitelistproof.data(), whitelistproof.size(), flags, bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int elements_pegout_script_size(size_t genesis_blockhash_len, size_t mainchain_script_len, size_t sub_pubkey_len, size_t whitelistproof_len, size_t* written) {
    int ret = ::wally_elements_pegout_script_size(genesis_blockhash_len, mainchain_script_len, sub_pubkey_len, whitelistproof_len, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class NONCE, class VBF, class COMMITMENT, class GENERATOR, class BYTES_OUT>
inline int explicit_rangeproof(uint64_t value, const NONCE& nonce, const VBF& vbf, const COMMITMENT& commitment, const GENERATOR& generator, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_explicit_rangeproof(value, nonce.data(), nonce.size(), vbf.data(), vbf.size(), commitment.data(), commitment.size(), generator.data(), generator.size(), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class RANGEPROOF, class COMMITMENT, class GENERATOR>
inline bool explicit_rangeproof_verify(const RANGEPROOF& rangeproof, uint64_t value, const COMMITMENT& commitment, const GENERATOR& generator) {
    int ret = ::wally_explicit_rangeproof_verify(rangeproof.data(), rangeproof.size(), value, commitment.data(), commitment.size(), generator.data(), generator.size());
    return ret == WALLY_OK;
}

template <class OUTPUT_ASSET, class OUTPUT_ABF, class OUTPUT_GENERATOR, class BYTES_OUT>
inline int explicit_surjectionproof(const OUTPUT_ASSET& output_asset, const OUTPUT_ABF& output_abf, const OUTPUT_GENERATOR& output_generator, BYTES_OUT& bytes_out) {
    int ret = ::wally_explicit_surjectionproof(output_asset.data(), output_asset.size(), output_abf.data(), output_abf.size(), output_generator.data(), output_generator.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SURJECTIONPROOF, class OUTPUT_ASSET, class OUTPUT_GENERATOR>
inline bool explicit_surjectionproof_verify(const SURJECTIONPROOF& surjectionproof, const OUTPUT_ASSET& output_asset, const OUTPUT_GENERATOR& output_generator) {
    int ret = ::wally_explicit_surjectionproof_verify(surjectionproof.data(), surjectionproof.size(), output_asset.data(), output_asset.size(), output_generator.data(), output_generator.size());
    return ret == WALLY_OK;
}

template <class PSBT, class SCALAR>
inline int psbt_add_global_scalar(const PSBT& psbt, const SCALAR& scalar) {
    int ret = ::wally_psbt_add_global_scalar(detail::get_p(psbt), scalar.data(), scalar.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT, class VALUES, class VBFS, class ASSETS, class ABFS, class ENTROPY>
inline int psbt_blind(const PSBT& psbt, const VALUES& values, const VBFS& vbfs, const ASSETS& assets, const ABFS& abfs, const ENTROPY& entropy, uint32_t output_index, uint32_t flags, struct wally_map* output) {
    int ret = ::wally_psbt_blind(detail::get_p(psbt), detail::get_p(values), detail::get_p(vbfs), detail::get_p(assets), detail::get_p(abfs), entropy.data(), entropy.size(), output_index, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT, class VALUES, class VBFS, class ASSETS, class ABFS, class ENTROPY>
inline int psbt_blind_alloc(const PSBT& psbt, const VALUES& values, const VBFS& vbfs, const ASSETS& assets, const ABFS& abfs, const ENTROPY& entropy, uint32_t output_index, uint32_t flags, struct wally_map** output) {
    int ret = ::wally_psbt_blind_alloc(detail::get_p(psbt), detail::get_p(values), detail::get_p(vbfs), detail::get_p(assets), detail::get_p(abfs), entropy.data(), entropy.size(), output_index, flags, output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT, class SCALAR>
inline int psbt_find_global_scalar(const PSBT& psbt, const SCALAR& scalar, size_t* written) {
    int ret = ::wally_psbt_find_global_scalar(detail::get_p(psbt), scalar.data(), scalar.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_amount_rangeproof(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_amount_rangeproof(input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_asset(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_asset(input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_asset_surjectionproof(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_asset_surjectionproof(input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_inflation_keys_blinding_rangeproof(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_inflation_keys_blinding_rangeproof(input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_inflation_keys_commitment(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_inflation_keys_commitment(input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_inflation_keys_rangeproof(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_inflation_keys_rangeproof(input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_issuance_amount_blinding_rangeproof(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_issuance_amount_blinding_rangeproof(input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_issuance_amount_commitment(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_issuance_amount_commitment(input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_issuance_amount_rangeproof(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_issuance_amount_rangeproof(input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_issuance_asset_entropy(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_issuance_asset_entropy(input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_issuance_blinding_nonce(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_issuance_blinding_nonce(input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_pegin_claim_script(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_pegin_claim_script(input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_pegin_genesis_blockhash(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_pegin_genesis_blockhash(input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_pegin_txout_proof(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_pegin_txout_proof(input);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_input_clear_utxo_rangeproof(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_utxo_rangeproof(input);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class ASSET, class ABF, class VBF, class ENTROPY>
inline int psbt_input_generate_explicit_proofs(const INPUT& input, uint64_t satoshi, const ASSET& asset, const ABF& abf, const VBF& vbf, const ENTROPY& entropy) {
    int ret = ::wally_psbt_input_generate_explicit_proofs(detail::get_p(input), satoshi, asset.data(), asset.size(), abf.data(), abf.size(), vbf.data(), vbf.size(), entropy.data(), entropy.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class BYTES_OUT>
inline int psbt_input_get_amount_rangeproof(const INPUT& input, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_input_get_amount_rangeproof(detail::get_p(input), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_get_amount_rangeproof_len(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_get_amount_rangeproof_len(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class BYTES_OUT>
inline int psbt_input_get_asset(const INPUT& input, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_input_get_asset(detail::get_p(input), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_get_asset_len(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_get_asset_len(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class BYTES_OUT>
inline int psbt_input_get_asset_surjectionproof(const INPUT& input, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_input_get_asset_surjectionproof(detail::get_p(input), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_get_asset_surjectionproof_len(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_get_asset_surjectionproof_len(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class BYTES_OUT>
inline int psbt_input_get_inflation_keys_blinding_rangeproof(const INPUT& input, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_input_get_inflation_keys_blinding_rangeproof(detail::get_p(input), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_get_inflation_keys_blinding_rangeproof_len(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_get_inflation_keys_blinding_rangeproof_len(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class BYTES_OUT>
inline int psbt_input_get_inflation_keys_commitment(const INPUT& input, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_input_get_inflation_keys_commitment(detail::get_p(input), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_get_inflation_keys_commitment_len(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_get_inflation_keys_commitment_len(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class BYTES_OUT>
inline int psbt_input_get_inflation_keys_rangeproof(const INPUT& input, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_input_get_inflation_keys_rangeproof(detail::get_p(input), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_get_inflation_keys_rangeproof_len(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_get_inflation_keys_rangeproof_len(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class BYTES_OUT>
inline int psbt_input_get_issuance_amount_blinding_rangeproof(const INPUT& input, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_input_get_issuance_amount_blinding_rangeproof(detail::get_p(input), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_get_issuance_amount_blinding_rangeproof_len(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_get_issuance_amount_blinding_rangeproof_len(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class BYTES_OUT>
inline int psbt_input_get_issuance_amount_commitment(const INPUT& input, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_input_get_issuance_amount_commitment(detail::get_p(input), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_get_issuance_amount_commitment_len(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_get_issuance_amount_commitment_len(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class BYTES_OUT>
inline int psbt_input_get_issuance_amount_rangeproof(const INPUT& input, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_input_get_issuance_amount_rangeproof(detail::get_p(input), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_get_issuance_amount_rangeproof_len(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_get_issuance_amount_rangeproof_len(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class BYTES_OUT>
inline int psbt_input_get_issuance_asset_entropy(const INPUT& input, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_input_get_issuance_asset_entropy(detail::get_p(input), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_get_issuance_asset_entropy_len(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_get_issuance_asset_entropy_len(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class BYTES_OUT>
inline int psbt_input_get_issuance_blinding_nonce(const INPUT& input, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_input_get_issuance_blinding_nonce(detail::get_p(input), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_get_issuance_blinding_nonce_len(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_get_issuance_blinding_nonce_len(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class BYTES_OUT>
inline int psbt_input_get_pegin_claim_script(const INPUT& input, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_input_get_pegin_claim_script(detail::get_p(input), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_get_pegin_claim_script_len(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_get_pegin_claim_script_len(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class BYTES_OUT>
inline int psbt_input_get_pegin_genesis_blockhash(const INPUT& input, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_input_get_pegin_genesis_blockhash(detail::get_p(input), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_get_pegin_genesis_blockhash_len(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_get_pegin_genesis_blockhash_len(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class BYTES_OUT>
inline int psbt_input_get_pegin_txout_proof(const INPUT& input, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_input_get_pegin_txout_proof(detail::get_p(input), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_get_pegin_txout_proof_len(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_get_pegin_txout_proof_len(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class BYTES_OUT>
inline int psbt_input_get_utxo_rangeproof(const INPUT& input, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_input_get_utxo_rangeproof(detail::get_p(input), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_get_utxo_rangeproof_len(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_get_utxo_rangeproof_len(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_amount(const INPUT& input, uint64_t amount) {
    int ret = ::wally_psbt_input_set_amount(detail::get_p(input), amount);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class RANGEPROOF>
inline int psbt_input_set_amount_rangeproof(const INPUT& input, const RANGEPROOF& rangeproof) {
    int ret = ::wally_psbt_input_set_amount_rangeproof(detail::get_p(input), rangeproof.data(), rangeproof.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class ASSET>
inline int psbt_input_set_asset(const INPUT& input, const ASSET& asset) {
    int ret = ::wally_psbt_input_set_asset(detail::get_p(input), asset.data(), asset.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class SURJECTIONPROOF>
inline int psbt_input_set_asset_surjectionproof(const INPUT& input, const SURJECTIONPROOF& surjectionproof) {
    int ret = ::wally_psbt_input_set_asset_surjectionproof(detail::get_p(input), surjectionproof.data(), surjectionproof.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_inflation_keys(const INPUT& input, uint64_t value) {
    int ret = ::wally_psbt_input_set_inflation_keys(detail::get_p(input), value);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class RANGEPROOF>
inline int psbt_input_set_inflation_keys_blinding_rangeproof(const INPUT& input, const RANGEPROOF& rangeproof) {
    int ret = ::wally_psbt_input_set_inflation_keys_blinding_rangeproof(detail::get_p(input), rangeproof.data(), rangeproof.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class COMMITMENT>
inline int psbt_input_set_inflation_keys_commitment(const INPUT& input, const COMMITMENT& commitment) {
    int ret = ::wally_psbt_input_set_inflation_keys_commitment(detail::get_p(input), commitment.data(), commitment.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class RANGEPROOF>
inline int psbt_input_set_inflation_keys_rangeproof(const INPUT& input, const RANGEPROOF& rangeproof) {
    int ret = ::wally_psbt_input_set_inflation_keys_rangeproof(detail::get_p(input), rangeproof.data(), rangeproof.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_issuance_amount(const INPUT& input, uint64_t amount) {
    int ret = ::wally_psbt_input_set_issuance_amount(detail::get_p(input), amount);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class RANGEPROOF>
inline int psbt_input_set_issuance_amount_blinding_rangeproof(const INPUT& input, const RANGEPROOF& rangeproof) {
    int ret = ::wally_psbt_input_set_issuance_amount_blinding_rangeproof(detail::get_p(input), rangeproof.data(), rangeproof.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class COMMITMENT>
inline int psbt_input_set_issuance_amount_commitment(const INPUT& input, const COMMITMENT& commitment) {
    int ret = ::wally_psbt_input_set_issuance_amount_commitment(detail::get_p(input), commitment.data(), commitment.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class RANGEPROOF>
inline int psbt_input_set_issuance_amount_rangeproof(const INPUT& input, const RANGEPROOF& rangeproof) {
    int ret = ::wally_psbt_input_set_issuance_amount_rangeproof(detail::get_p(input), rangeproof.data(), rangeproof.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class ENTROPY>
inline int psbt_input_set_issuance_asset_entropy(const INPUT& input, const ENTROPY& entropy) {
    int ret = ::wally_psbt_input_set_issuance_asset_entropy(detail::get_p(input), entropy.data(), entropy.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class NONCE>
inline int psbt_input_set_issuance_blinding_nonce(const INPUT& input, const NONCE& nonce) {
    int ret = ::wally_psbt_input_set_issuance_blinding_nonce(detail::get_p(input), nonce.data(), nonce.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_pegin_amount(const INPUT& input, uint64_t amount) {
    int ret = ::wally_psbt_input_set_pegin_amount(detail::get_p(input), amount);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class SCRIPT>
inline int psbt_input_set_pegin_claim_script(const INPUT& input, const SCRIPT& script) {
    int ret = ::wally_psbt_input_set_pegin_claim_script(detail::get_p(input), script.data(), script.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class GENESIS_BLOCKHASH>
inline int psbt_input_set_pegin_genesis_blockhash(const INPUT& input, const GENESIS_BLOCKHASH& genesis_blockhash) {
    int ret = ::wally_psbt_input_set_pegin_genesis_blockhash(detail::get_p(input), genesis_blockhash.data(), genesis_blockhash.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_pegin_tx(const INPUT& input, const struct wally_tx* tx) {
    int ret = ::wally_psbt_input_set_pegin_tx(detail::get_p(input), tx);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class TXOUT_PROOF>
inline int psbt_input_set_pegin_txout_proof(const INPUT& input, const TXOUT_PROOF& txout_proof) {
    int ret = ::wally_psbt_input_set_pegin_txout_proof(detail::get_p(input), txout_proof.data(), txout_proof.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int psbt_input_set_pegin_witness(const INPUT& input, const struct wally_tx_witness_stack* witness) {
    int ret = ::wally_psbt_input_set_pegin_witness(detail::get_p(input), witness);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class RANGEPROOF>
inline int psbt_input_set_utxo_rangeproof(const INPUT& input, const RANGEPROOF& rangeproof) {
    int ret = ::wally_psbt_input_set_utxo_rangeproof(detail::get_p(input), rangeproof.data(), rangeproof.size());
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_output_clear_asset(struct wally_psbt_output* output) {
    int ret = ::wally_psbt_output_clear_asset(output);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_output_clear_asset_blinding_surjectionproof(struct wally_psbt_output* output) {
    int ret = ::wally_psbt_output_clear_asset_blinding_surjectionproof(output);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_output_clear_asset_commitment(struct wally_psbt_output* output) {
    int ret = ::wally_psbt_output_clear_asset_commitment(output);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_output_clear_asset_surjectionproof(struct wally_psbt_output* output) {
    int ret = ::wally_psbt_output_clear_asset_surjectionproof(output);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_output_clear_blinder_index(struct wally_psbt_output* output) {
    int ret = ::wally_psbt_output_clear_blinder_index(output);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_output_clear_blinding_public_key(struct wally_psbt_output* output) {
    int ret = ::wally_psbt_output_clear_blinding_public_key(output);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_output_clear_ecdh_public_key(struct wally_psbt_output* output) {
    int ret = ::wally_psbt_output_clear_ecdh_public_key(output);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_output_clear_value_blinding_rangeproof(struct wally_psbt_output* output) {
    int ret = ::wally_psbt_output_clear_value_blinding_rangeproof(output);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_output_clear_value_commitment(struct wally_psbt_output* output) {
    int ret = ::wally_psbt_output_clear_value_commitment(output);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int psbt_output_clear_value_rangeproof(struct wally_psbt_output* output) {
    int ret = ::wally_psbt_output_clear_value_rangeproof(output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class BYTES_OUT>
inline int psbt_output_get_asset(const OUTPUT& output, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_output_get_asset(detail::get_p(output), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class BYTES_OUT>
inline int psbt_output_get_asset_blinding_surjectionproof(const OUTPUT& output, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_output_get_asset_blinding_surjectionproof(detail::get_p(output), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT>
inline int psbt_output_get_asset_blinding_surjectionproof_len(const OUTPUT& output, size_t* written) {
    int ret = ::wally_psbt_output_get_asset_blinding_surjectionproof_len(detail::get_p(output), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class BYTES_OUT>
inline int psbt_output_get_asset_commitment(const OUTPUT& output, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_output_get_asset_commitment(detail::get_p(output), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT>
inline int psbt_output_get_asset_commitment_len(const OUTPUT& output, size_t* written) {
    int ret = ::wally_psbt_output_get_asset_commitment_len(detail::get_p(output), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT>
inline int psbt_output_get_asset_len(const OUTPUT& output, size_t* written) {
    int ret = ::wally_psbt_output_get_asset_len(detail::get_p(output), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class BYTES_OUT>
inline int psbt_output_get_asset_surjectionproof(const OUTPUT& output, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_output_get_asset_surjectionproof(detail::get_p(output), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT>
inline int psbt_output_get_asset_surjectionproof_len(const OUTPUT& output, size_t* written) {
    int ret = ::wally_psbt_output_get_asset_surjectionproof_len(detail::get_p(output), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class BYTES_OUT>
inline int psbt_output_get_blinding_public_key(const OUTPUT& output, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_output_get_blinding_public_key(detail::get_p(output), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT>
inline int psbt_output_get_blinding_public_key_len(const OUTPUT& output, size_t* written) {
    int ret = ::wally_psbt_output_get_blinding_public_key_len(detail::get_p(output), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT>
inline int psbt_output_get_blinding_status(const OUTPUT& output, uint32_t flags, size_t* written) {
    int ret = ::wally_psbt_output_get_blinding_status(detail::get_p(output), flags, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class BYTES_OUT>
inline int psbt_output_get_ecdh_public_key(const OUTPUT& output, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_output_get_ecdh_public_key(detail::get_p(output), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT>
inline int psbt_output_get_ecdh_public_key_len(const OUTPUT& output, size_t* written) {
    int ret = ::wally_psbt_output_get_ecdh_public_key_len(detail::get_p(output), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class BYTES_OUT>
inline int psbt_output_get_value_blinding_rangeproof(const OUTPUT& output, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_output_get_value_blinding_rangeproof(detail::get_p(output), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT>
inline int psbt_output_get_value_blinding_rangeproof_len(const OUTPUT& output, size_t* written) {
    int ret = ::wally_psbt_output_get_value_blinding_rangeproof_len(detail::get_p(output), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class BYTES_OUT>
inline int psbt_output_get_value_commitment(const OUTPUT& output, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_output_get_value_commitment(detail::get_p(output), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT>
inline int psbt_output_get_value_commitment_len(const OUTPUT& output, size_t* written) {
    int ret = ::wally_psbt_output_get_value_commitment_len(detail::get_p(output), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class BYTES_OUT>
inline int psbt_output_get_value_rangeproof(const OUTPUT& output, BYTES_OUT& bytes_out, size_t* written) {
    int ret = ::wally_psbt_output_get_value_rangeproof(detail::get_p(output), bytes_out.data(), bytes_out.size(), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT>
inline int psbt_output_get_value_rangeproof_len(const OUTPUT& output, size_t* written) {
    int ret = ::wally_psbt_output_get_value_rangeproof_len(detail::get_p(output), written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class ASSET>
inline int psbt_output_set_asset(const OUTPUT& output, const ASSET& asset) {
    int ret = ::wally_psbt_output_set_asset(detail::get_p(output), asset.data(), asset.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class SURJECTIONPROOF>
inline int psbt_output_set_asset_blinding_surjectionproof(const OUTPUT& output, const SURJECTIONPROOF& surjectionproof) {
    int ret = ::wally_psbt_output_set_asset_blinding_surjectionproof(detail::get_p(output), surjectionproof.data(), surjectionproof.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class COMMITMENT>
inline int psbt_output_set_asset_commitment(const OUTPUT& output, const COMMITMENT& commitment) {
    int ret = ::wally_psbt_output_set_asset_commitment(detail::get_p(output), commitment.data(), commitment.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class SURJECTIONPROOF>
inline int psbt_output_set_asset_surjectionproof(const OUTPUT& output, const SURJECTIONPROOF& surjectionproof) {
    int ret = ::wally_psbt_output_set_asset_surjectionproof(detail::get_p(output), surjectionproof.data(), surjectionproof.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT>
inline int psbt_output_set_blinder_index(const OUTPUT& output, uint32_t index) {
    int ret = ::wally_psbt_output_set_blinder_index(detail::get_p(output), index);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class PUB_KEY>
inline int psbt_output_set_blinding_public_key(const OUTPUT& output, const PUB_KEY& pub_key) {
    int ret = ::wally_psbt_output_set_blinding_public_key(detail::get_p(output), pub_key.data(), pub_key.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class PUB_KEY>
inline int psbt_output_set_ecdh_public_key(const OUTPUT& output, const PUB_KEY& pub_key) {
    int ret = ::wally_psbt_output_set_ecdh_public_key(detail::get_p(output), pub_key.data(), pub_key.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class RANGEPROOF>
inline int psbt_output_set_value_blinding_rangeproof(const OUTPUT& output, const RANGEPROOF& rangeproof) {
    int ret = ::wally_psbt_output_set_value_blinding_rangeproof(detail::get_p(output), rangeproof.data(), rangeproof.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class COMMITMENT>
inline int psbt_output_set_value_commitment(const OUTPUT& output, const COMMITMENT& commitment) {
    int ret = ::wally_psbt_output_set_value_commitment(detail::get_p(output), commitment.data(), commitment.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class RANGEPROOF>
inline int psbt_output_set_value_rangeproof(const OUTPUT& output, const RANGEPROOF& rangeproof) {
    int ret = ::wally_psbt_output_set_value_rangeproof(detail::get_p(output), rangeproof.data(), rangeproof.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_set_global_scalars(const PSBT& psbt, const struct wally_map* map_in) {
    int ret = ::wally_psbt_set_global_scalars(detail::get_p(psbt), map_in);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class PSBT>
inline int psbt_set_pset_modifiable_flags(const PSBT& psbt, uint32_t flags) {
    int ret = ::wally_psbt_set_pset_modifiable_flags(detail::get_p(psbt), flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX, class TXHASH, class SCRIPT, class WITNESS, class NONCE, class ENTROPY, class ISSUANCE_AMOUNT, class INFLATION_KEYS, class ISSUANCE_AMOUNT_RANGEPROOF, class INFLATION_KEYS_RANGEPROOF, class PEGIN_WITNESS>
inline int tx_add_elements_raw_input(const TX& tx, const TXHASH& txhash, uint32_t utxo_index, uint32_t sequence, const SCRIPT& script, const WITNESS& witness, const NONCE& nonce, const ENTROPY& entropy, const ISSUANCE_AMOUNT& issuance_amount, const INFLATION_KEYS& inflation_keys, const ISSUANCE_AMOUNT_RANGEPROOF& issuance_amount_rangeproof, const INFLATION_KEYS_RANGEPROOF& inflation_keys_rangeproof, const PEGIN_WITNESS& pegin_witness, uint32_t flags) {
    int ret = ::wally_tx_add_elements_raw_input(detail::get_p(tx), txhash.data(), txhash.size(), utxo_index, sequence, script.data(), script.size(), detail::get_p(witness), nonce.data(), nonce.size(), entropy.data(), entropy.size(), issuance_amount.data(), issuance_amount.size(), inflation_keys.data(), inflation_keys.size(), issuance_amount_rangeproof.data(), issuance_amount_rangeproof.size(), inflation_keys_rangeproof.data(), inflation_keys_rangeproof.size(), detail::get_p(pegin_witness), flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX, class TXHASH, class SCRIPT, class WITNESS, class NONCE, class ENTROPY, class ISSUANCE_AMOUNT, class INFLATION_KEYS, class ISSUANCE_AMOUNT_RANGEPROOF, class INFLATION_KEYS_RANGEPROOF, class PEGIN_WITNESS>
inline int tx_add_elements_raw_input_at(const TX& tx, uint32_t index, const TXHASH& txhash, uint32_t utxo_index, uint32_t sequence, const SCRIPT& script, const WITNESS& witness, const NONCE& nonce, const ENTROPY& entropy, const ISSUANCE_AMOUNT& issuance_amount, const INFLATION_KEYS& inflation_keys, const ISSUANCE_AMOUNT_RANGEPROOF& issuance_amount_rangeproof, const INFLATION_KEYS_RANGEPROOF& inflation_keys_rangeproof, const PEGIN_WITNESS& pegin_witness, uint32_t flags) {
    int ret = ::wally_tx_add_elements_raw_input_at(detail::get_p(tx), index, txhash.data(), txhash.size(), utxo_index, sequence, script.data(), script.size(), detail::get_p(witness), nonce.data(), nonce.size(), entropy.data(), entropy.size(), issuance_amount.data(), issuance_amount.size(), inflation_keys.data(), inflation_keys.size(), issuance_amount_rangeproof.data(), issuance_amount_rangeproof.size(), inflation_keys_rangeproof.data(), inflation_keys_rangeproof.size(), detail::get_p(pegin_witness), flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX, class SCRIPT, class ASSET, class VALUE, class NONCE, class SURJECTIONPROOF, class RANGEPROOF>
inline int tx_add_elements_raw_output(const TX& tx, const SCRIPT& script, const ASSET& asset, const VALUE& value, const NONCE& nonce, const SURJECTIONPROOF& surjectionproof, const RANGEPROOF& rangeproof, uint32_t flags) {
    int ret = ::wally_tx_add_elements_raw_output(detail::get_p(tx), script.data(), script.size(), asset.data(), asset.size(), value.data(), value.size(), nonce.data(), nonce.size(), surjectionproof.data(), surjectionproof.size(), rangeproof.data(), rangeproof.size(), flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX, class SCRIPT, class ASSET, class VALUE, class NONCE, class SURJECTIONPROOF, class RANGEPROOF>
inline int tx_add_elements_raw_output_at(const TX& tx, uint32_t index, const SCRIPT& script, const ASSET& asset, const VALUE& value, const NONCE& nonce, const SURJECTIONPROOF& surjectionproof, const RANGEPROOF& rangeproof, uint32_t flags) {
    int ret = ::wally_tx_add_elements_raw_output_at(detail::get_p(tx), index, script.data(), script.size(), asset.data(), asset.size(), value.data(), value.size(), nonce.data(), nonce.size(), surjectionproof.data(), surjectionproof.size(), rangeproof.data(), rangeproof.size(), flags);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class BYTES_OUT>
inline int tx_confidential_value_from_satoshi(uint64_t satoshi, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_confidential_value_from_satoshi(satoshi, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class VALUE>
inline int tx_confidential_value_to_satoshi(const VALUE& value, uint64_t* value_out) {
    int ret = ::wally_tx_confidential_value_to_satoshi(value.data(), value.size(), value_out);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TXHASH, class SCRIPT, class WITNESS, class NONCE, class ENTROPY, class ISSUANCE_AMOUNT, class INFLATION_KEYS, class ISSUANCE_AMOUNT_RANGEPROOF, class INFLATION_KEYS_RANGEPROOF, class PEGIN_WITNESS>
inline int tx_elements_input_init_alloc(const TXHASH& txhash, uint32_t utxo_index, uint32_t sequence, const SCRIPT& script, const WITNESS& witness, const NONCE& nonce, const ENTROPY& entropy, const ISSUANCE_AMOUNT& issuance_amount, const INFLATION_KEYS& inflation_keys, const ISSUANCE_AMOUNT_RANGEPROOF& issuance_amount_rangeproof, const INFLATION_KEYS_RANGEPROOF& inflation_keys_rangeproof, const PEGIN_WITNESS& pegin_witness, struct wally_tx_input** output) {
    int ret = ::wally_tx_elements_input_init_alloc(txhash.data(), txhash.size(), utxo_index, sequence, script.data(), script.size(), detail::get_p(witness), nonce.data(), nonce.size(), entropy.data(), entropy.size(), issuance_amount.data(), issuance_amount.size(), inflation_keys.data(), inflation_keys.size(), issuance_amount_rangeproof.data(), issuance_amount_rangeproof.size(), inflation_keys_rangeproof.data(), inflation_keys_rangeproof.size(), detail::get_p(pegin_witness), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT>
inline int tx_elements_input_is_pegin(const INPUT& input, size_t* written) {
    int ret = ::wally_tx_elements_input_is_pegin(detail::get_p(input), written);
    return detail::check_ret(__FUNCTION__, ret);
}

inline int tx_elements_input_issuance_free(struct wally_tx_input* input) {
    int ret = ::wally_tx_elements_input_issuance_free(input);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class INPUT, class NONCE, class ENTROPY, class ISSUANCE_AMOUNT, class INFLATION_KEYS, class ISSUANCE_AMOUNT_RANGEPROOF, class INFLATION_KEYS_RANGEPROOF>
inline int tx_elements_input_issuance_set(const INPUT& input, const NONCE& nonce, const ENTROPY& entropy, const ISSUANCE_AMOUNT& issuance_amount, const INFLATION_KEYS& inflation_keys, const ISSUANCE_AMOUNT_RANGEPROOF& issuance_amount_rangeproof, const INFLATION_KEYS_RANGEPROOF& inflation_keys_rangeproof) {
    int ret = ::wally_tx_elements_input_issuance_set(detail::get_p(input), nonce.data(), nonce.size(), entropy.data(), entropy.size(), issuance_amount.data(), issuance_amount.size(), inflation_keys.data(), inflation_keys.size(), issuance_amount_rangeproof.data(), issuance_amount_rangeproof.size(), inflation_keys_rangeproof.data(), inflation_keys_rangeproof.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ENTROPY, class BYTES_OUT>
inline int tx_elements_issuance_calculate_asset(const ENTROPY& entropy, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_elements_issuance_calculate_asset(entropy.data(), entropy.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class ENTROPY, class BYTES_OUT>
inline int tx_elements_issuance_calculate_reissuance_token(const ENTROPY& entropy, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_elements_issuance_calculate_reissuance_token(entropy.data(), entropy.size(), flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TXHASH, class CONTRACT_HASH, class BYTES_OUT>
inline int tx_elements_issuance_generate_entropy(const TXHASH& txhash, uint32_t utxo_index, const CONTRACT_HASH& contract_hash, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_elements_issuance_generate_entropy(txhash.data(), txhash.size(), utxo_index, contract_hash.data(), contract_hash.size(), bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

inline int tx_elements_output_commitment_free(struct wally_tx_output* output) {
    int ret = ::wally_tx_elements_output_commitment_free(output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class OUTPUT, class ASSET, class VALUE, class NONCE, class SURJECTIONPROOF, class RANGEPROOF>
inline int tx_elements_output_commitment_set(const OUTPUT& output, const ASSET& asset, const VALUE& value, const NONCE& nonce, const SURJECTIONPROOF& surjectionproof, const RANGEPROOF& rangeproof) {
    int ret = ::wally_tx_elements_output_commitment_set(detail::get_p(output), asset.data(), asset.size(), value.data(), value.size(), nonce.data(), nonce.size(), surjectionproof.data(), surjectionproof.size(), rangeproof.data(), rangeproof.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SCRIPT, class ASSET, class VALUE, class NONCE, class SURJECTIONPROOF, class RANGEPROOF>
inline int tx_elements_output_init(const SCRIPT& script, const ASSET& asset, const VALUE& value, const NONCE& nonce, const SURJECTIONPROOF& surjectionproof, const RANGEPROOF& rangeproof, struct wally_tx_output* output) {
    int ret = ::wally_tx_elements_output_init(script.data(), script.size(), asset.data(), asset.size(), value.data(), value.size(), nonce.data(), nonce.size(), surjectionproof.data(), surjectionproof.size(), rangeproof.data(), rangeproof.size(), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class SCRIPT, class ASSET, class VALUE, class NONCE, class SURJECTIONPROOF, class RANGEPROOF>
inline int tx_elements_output_init_alloc(const SCRIPT& script, const ASSET& asset, const VALUE& value, const NONCE& nonce, const SURJECTIONPROOF& surjectionproof, const RANGEPROOF& rangeproof, struct wally_tx_output** output) {
    int ret = ::wally_tx_elements_output_init_alloc(script.data(), script.size(), asset.data(), asset.size(), value.data(), value.size(), nonce.data(), nonce.size(), surjectionproof.data(), surjectionproof.size(), rangeproof.data(), rangeproof.size(), output);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX, class SCRIPT, class VALUE, class BYTES_OUT>
inline int tx_get_elements_signature_hash(const TX& tx, size_t index, const SCRIPT& script, const VALUE& value, uint32_t sighash, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_get_elements_signature_hash(detail::get_p(tx), index, script.data(), script.size(), value.data(), value.size(), sighash, flags, bytes_out.data(), bytes_out.size());
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_get_elements_weight_discount(const TX& tx, uint32_t flags, size_t* written) {
    int ret = ::wally_tx_get_elements_weight_discount(detail::get_p(tx), flags, written);
    return detail::check_ret(__FUNCTION__, ret);
}

template <class TX>
inline int tx_is_elements(const TX& tx, size_t* written) {
    int ret = ::wally_tx_is_elements(detail::get_p(tx), written);
    return detail::check_ret(__FUNCTION__, ret);
}
#endif // WALLY_ABI_NO_ELEMENTS
/* END AUTOGENERATED */

inline struct secp256k1_context_struct *get_secp_context() {
    return ::wally_get_secp_context();
}

inline struct secp256k1_context_struct *get_new_secp_context() {
    return ::wally_get_new_secp_context();
}

inline void secp_context_free(struct secp256k1_context_struct *ctx) {
    ::wally_secp_context_free(ctx);
}

inline int clear(void *p, size_t n) {
    return ::wally_bzero(p, n);
}

template<typename O> inline int clear(O& out) {
    return ::wally_bzero(out.data(), out.size());
}

inline bool is_elements_build()
{
    size_t ret;
    ::wally_is_elements_build(&ret);
    return ret != 0;
}

} /* namespace wally */

#endif /* LIBWALLY_CORE_WALLY_HPP */
